Wie starte ich tmux automatisch in einer SSH-Sitzung?

91

Ich habe ungefähr zehn Server, mit denen ich mich regelmäßig mit SSH verbinde. Jeder hat einen Eintrag in der ~/.ssh/configDatei meines lokalen Computers .

Um zu vermeiden, dass ich die Kontrolle über meinen laufenden Prozess verliere, wenn meine Internetverbindung unvermeidlich unterbrochen wird, arbeite ich immer in einer tmuxSitzung. Ich möchte, dass tmux jedes Mal, wenn eine SSH-Verbindung gestartet wird, automatisch eine Verbindung herstellt, sodass ich nicht immer tmux attach || tmux newnach dem SSH eingeben muss .

Leider ist dies nicht so einfach, wie ich es mir ursprünglich erhofft hatte.

  • Ich möchte ~/.bashrcden Servern auf den Servern keine Befehle hinzufügen, da ich sie nur für SSH-Sitzungen und nicht für lokale Sitzungen verwenden möchte.
  • Das Hinzufügen tmux attach || tmux newzu den ~/.ssh/rcServern führt einfach dazu, dass der Fehler not a terminalnach der Verbindung ausgelöst wird, selbst wenn die RequestTTY forceOption der Zeile für diesen Server in meiner lokalen SSH-Konfigurationsdatei hinzugefügt wird.
Alex Ryan
quelle
1
Da dies weiterhin eine beliebte Frage ist und ausdrücklich erwähnt wird ~/.ssh/config: Die meisten von Ihnen, die hierher kommen, suchen wahrscheinlich nicht nach einer der ersten fünf Antworten, sondern nach der sechsten ( stackoverflow.com/a/52838493/5354137 ). Mit jeder einigermaßen aktuellen tmuxVersion ist dies auch die sinnvollste Art, Dinge zu tun.
Fünfundsechzig

Antworten:

90

Serverseitige Konfiguration:

Um tmux automatisch auf Ihrem Remote-Server zu starten, wenn Sie sich normalerweise über SSH (und nur über SSH) anmelden, bearbeiten Sie das ~/.bashrcIhres Benutzers oder Root (oder beides) auf dem Remote-Server entsprechend:

if [[ -n "$PS1" ]] && [[ -z "$TMUX" ]] && [[ -n "$SSH_CONNECTION" ]]; then
  tmux attach-session -t ssh_tmux || tmux new-session -s ssh_tmux
fi

Dieser Befehl erstellt eine tmux-Sitzung, die aufgerufen wird, ssh_tmuxwenn keine vorhanden ist, oder stellt eine Verbindung zu einer bereits vorhandenen Sitzung mit diesem Namen her. Falls Ihre Verbindung unterbrochen wurde oder Sie vor Wochen eine Sitzung vergessen haben, bringt Sie jede SSH-Anmeldung automatisch zu der tmux-ssh-Sitzung zurück, die Sie zurückgelassen haben.

Verbinden Sie sich von Ihrem Client aus:

Nichts Besonderes, nur ssh user@hostname.

kingmeffisto
quelle
4
Ich habe danach gesucht, auch ich habe vor einiger Zeit einen Code verwendet, der ssh_tmux$USER
Ihrem sehr ähnlich
3
Siehe moneytoo die Antwort für nützlichen Kommentar zu $SSH_TTYvs $SSH_CONNECTIONauch.
Herr Tao
2
Sie können verwenden tmux new-session -A -s ssh_tmux, um tmux attach-session -t ssh_tmux || tmux new-session -s ssh_tmuxviel kürzer zu ersetzen , wenn etwas verwirrender, -Atmux anweist, die Sitzung anzuhängen, wenn es bereits existiert
Gradient
3
Um zu vermeiden, dass "scp" beschädigt wird, müssen Sie auch überprüfen, ob dies eine interaktive Shell ist:if [[ -n "$PS1" ]] && [[ -z "$TMUX" ]] && [[ -n "$SSH_CONNECTION" ]];
Janfrode
2
@janfrode verlässt sich nicht auf $PS1, [[ $- == *i* ]]sondern verwendet stattdessen PS1, auch wenn es sich nicht um eine interaktive Shell handelt.
Enrico
52

Okay, ich habe eine meist zufriedenstellende Lösung gefunden. In meinem Lokal habe ~/.bashrcich eine Funktion geschrieben:

function ssh () {/usr/bin/ssh -t $@ "tmux attach || tmux new";}

Dies überschreibt im Grunde die ssh-Terminalfunktion, um das eingebaute ssh-Programm mit den angegebenen Argumenten aufzurufen, gefolgt von "tmux attach || tmux new".

(Das $@bezeichnet alle in der Befehlszeile angegebenen Argumente und ssh -p 123 user@hostnamewird daher auf erweitert. ssh -t -p 123 user@hostname "tmux attach || tmux new")

(Das -tArgument entspricht RequestTTY Forcedem Befehl tmux und ist für diesen erforderlich.)

Alex Ryan
quelle
22
Wenn Ihre Version dies tmuxunterstützt, sollten Sie in Betracht ziehen, zu verwenden, tmux new -A foowelche an eine vorhandene Sitzung mit dem Namen fooangehängt wird, wenn möglich, und sie gegebenenfalls erstellen. Auf diese Weise können Sie Ihre Funktion vereinfachen /usr/bin/ssh -t "$@" tmux new -A(und unbedingt zitieren $@!).
Chepner
1
Hinweis: Wenn auf einigen Computern, mit denen Sie regelmäßig eine Verbindung herstellen, tmux nicht installiert ist, möchten Sie möglicherweise Folgendes sagen, function sshtdamit Sie die sshnormale Verwendung fortsetzen können. Andernfalls geben Sie einfach /usr/bin/sshan der Eingabeaufforderung ein, wenn Sie eine Verbindung zu einem Computer ohne tmux herstellen :)
Alex Ryan
1
Wenn Sie faul sind, können Sie einfach ssht verwenden , um eine Verbindung zu Ihren Remote-tmux-Sitzungen herzustellen. O X - Benutzer kann es über Gebräu tippen und Linux - Benutzer können ein Paket über erstellen fpm mit diesem Makefile oder einfach kopieren sshtzu ~/bin.
Brejoc
1
Haha schön! Es scheint mir ein bisschen übertrieben zu sein, diesen Bash-Einzeiler in ein ganzes Github-Repo mit Makefiles zu wickeln und zu brauen und so, aber hey, je einfacher desto besser!
Alex Ryan
1
Gelöst:ssh -t user@hostname "LANG=$LANG tmux attach || tmux new"
Alecdwm
23

Verbinden:

ssh user@host -t "tmux new-session -s user || tmux attach-session -t user"

Während der Sitzung:

Verwenden Sie Ctrl+ddiese Option , um die Sitzung zu beenden (das tmux-Fenster wird geschlossen) oder Ctrl+b dum sich vorübergehend von der Sitzung zu trennen und später erneut eine Verbindung herzustellen .

Merken! Wenn Ihr Server die Sitzung neu gestartet hat, ist sie verloren!

Wenn Sie in tmux jederzeit sind , können Sie verwenden , Ctrl+b sum zu sehen Sitzungen Liste und Schaltstrom zu einem anderen.

Korrigieren Sie Ihre .bashrc:

Ich empfehle Ihnen, die universelle Funktion in Ihrem zu definieren .bashrc:

function tmux-connect {
    TERM=xterm-256color ssh -p ${3:-22} $1@$2 -t "tmux new-session -s $1 || tmux attach-session -t $1"
}

22Standardmäßig wird der Port verwendet . Definieren Sie auch Ihre Fast-Connect-Aliase:

alias office-server='tmux-connect $USER 192.168.1.123'
alias cloud-server='tmux-connect root my.remote.vps.server.com 49281'

Login ohne Passwort:

Und wenn Sie nicht jedes Mal ein Passwort eingeben möchten, generieren Sie .sshSchlüssel, um sich automatisch anzumelden :

ssh-keygen -t rsa
eval "$(ssh-agent -s)" && ssh-add ~/.ssh/id_rsa

Legen Sie Ihren öffentlichen Schlüssel auf dem Remote-Host ab:

ssh-copy-id -p <port> user@hostname

Zusätzliche Tipps:

Wenn Sie eine temporäre Sitzungs-ID verwenden möchten, die einer lokalen Bash-Sitzung entspricht, verwenden Sie diese als tmux- ID:

SID=$USER-$BASHPID
ssh user@host -t "tmux new-session -s $SID || tmux attach-session -t $SID"
DenisKolodin
quelle
1
Ein netter Trick zu vermeiden , dass ||in einigen Anwendungsfällen ist enthalten new-sessionin .tmux.confund einfach immer verwenden tmux a -t 0.
Florian Wendelborn
4
In neueren Versionen von tmux können Sie auch verwenden, tmux new-session -Awelche angehängt werden, falls vorhanden, andernfalls wird eine neue erstellt.
Dragon788
15

Ich habe Zeilen von @kingmeffisto verwendet (ich darf diese Antwort nicht kommentieren) und einen Exit hinzugefügt, damit durch das Beenden von tmux auch die ssh-Verbindung beendet wird. Dies brach jedoch SFTP-Sitzungen, so dass ich $SSH_TTYstatt suchen musste $SSH_CONNECTION.

EDIT 4/2018: Test für interaktives Terminal über hinzugefügt [[ $- =~ i ]], damit Tools wie Ansible funktionieren können.

if [ -z "$TMUX" ] && [ -n "$SSH_TTY" ] && [[ $- =~ i ]]; then
    tmux attach-session -t ssh || tmux new-session -s ssh
    exit
fi
Geld zu viel
quelle
14

Wie in diesem Blog-Beitrag beschrieben , können Sie mit einem einzigen Befehl ssh und dann eine Verbindung zu einer vorhandenen tmux-Sitzung herstellen:

ssh hostname -t tmux attach -t 0
Fabian Pedregosa
quelle
Das ist meine Antwort (obwohl ich sie verwende, tmux attach || tmux newdamit nicht für jede Verbindung eine neue tmux-Sitzung erstellt wird). Der schwierige Teil ist, dass der richtige Befehl ist ssh -t user@host tmux attach || tmux newund der einzige Weg, etwas zu aliasen, das ein Argument in der Befehlszeichenfolge benötigt, darin besteht, eine neue Funktion zu erstellen, wie ich es oben getan habe.
Alex Ryan
Ich weiß, aber einige Leute (wie ich) bevorzugen vielleicht einen Einzeiler, bei dem keine Funktion definiert wird
Fabian Pedregosa,
3
Dies stellt eine Verbindung zu einer Sitzung mit dem Namen '0' her. Das heißt, die allgemeine Form istssh [hostname] -t tmux attach -t [sessionName]
David Doria
1
Das hat wirklich gut für mich funktioniert. Kombiniert wird dies unix.stackexchange.com/a/116674 . Jetzt sieht meine Kitt-GUI so aus. Imgur.com/uFhxN30 . Ich kann die Sitzungen mit Cntrl + b + d trennen. Sehr einfach und bequem ..
alpha_989
14

tmux 3.1 oder neuer¹ auf dem Remote-Computer

In Ihrem lokalen ~/.ssh/config, put²:

Host myhost
  Hostname host
  User user
  RequestTTY yes
  RemoteCommand tmux new -A -s foobar

Unabhängig, aber wenn Sie mit Nicht-ASCII-Zeichen arbeiten, würde ich empfehlen, dies zu ändern, tmux -u …um die Unicode-Unterstützung auch auf Computern explizit zu aktivieren, auf denen nicht die richtigen Umgebungsvariablen festgelegt sind.

tmux 3.0a oder älter auf dem Remote-Computer

Fast das gleiche wie oben, aber ändern Sie die letzte Zeile in ³:

  RemoteCommand tmux at -t foobar || tmux new -s foobar

¹ Ab dem 29.10.2020 ist die Liste der Distributionen, die mit tmux 3.1 oder neuer ausgeliefert werden, bereits ziemlich lang.

² newist die Abkürzung für new-session.

³ atist die Abkürzung für attach-session.


Alternative Methode unter Verwendung der Remote- authorized_keysDatei:

Wenn Sie ~/.ssh/configaus irgendeinem Grund lieber keine Datei haben möchten oder möchten, dass der Remotecomputer den Verbindungscomputer zwingt, eine Verbindung zur Sitzung herzustellen oder diese zu öffnen, fügen Sie diese zu Ihrer Remote hinzu ~/.ssh/authorized_keys:

command="tmux at -t foobar || tmux new -s foobar" pubkey user@client

Dies funktioniert natürlich von allen Clients, auf denen der entsprechende private Schlüssel installiert ist. Dies kann je nach Wunsch entweder ein Vorteil oder ein Nachteil sein. Es besteht die Gefahr, dass im Falle eines Fehlers möglicherweise keine Verbindung mehr hergestellt werden kann.

Fünfundsechzig
quelle
warum tmux atstatt tmux a? Es wäre auch ratsam, eine benannte Sitzung für diese zu verwenden, oder tmux würde beim Anmelden am Host an "zufällige" vorhandene Sitzungen angehängt.
Eric
Wie unterbrechen Sie die tmux-Sitzung? ssh geht nach dem Schlagen in den Zustand der Kindda-Schwebe Ctrl+A Ctrl+Z.
Eric
Es wird einfach getrennt. Für mich ist das das Verhalten, das ich erwarten würde und mit dem ich zufrieden bin.
Fünfundsechzig
1
Ctrl-B DWerke behandeln im Vergleich zu Ctrl-B Ctrl-Z. Vielen Dank!
Eric
1
Dies sollte imho die am häufigsten gewählte Antwort sein. Ich habe genau nach (2) gesucht.
CDuguet
1

byobu ist ein netter nützlicher Wrapper für tmux / screen. Stellt eine Verbindung zu einer vorhandenen Sitzung her, falls vorhanden, oder erstellt eine neue.

Ich benutze es mit Autossh, das die SSH-Sitzung ordnungsgemäß wieder verbindet. Sehr zu empfehlen bei zeitweiligen Verbindungsproblemen.

function ssh-tmux(){
  if ! command -v autossh &> /dev/null; then echo "Install autossh"; fi
  autossh -M 0 $* -t 'byobu || {echo "Install byobu-tmux on server..."} && bash'
}
Sandeep
quelle
1

Dies ist möglicherweise hilfreich - verwendet ssh in einer Schleife und stellt eine Verbindung zu einer vorhandenen tmux-Sitzung her oder stellt eine Verbindung zu dieser her, sodass Sie nach einem Netzwerkausfall eine einfache und zuverlässige Möglichkeit haben, die Verbindung wiederherzustellen

#!/bin/bash
#
# reconnect to or spawn a new tmux session on the remote host via ssh.
# If the network connection is lost, ssh will reconnect after a small
# delay.
#

SSH_HOSTNAME=$1
TMUX_NAME=$2
PORT=$3

if [[ "$PORT" != "" ]]
then
    PORT="-p $PORT"
fi

if [ "$TMUX_NAME" = "" ]
then
    SSH_UNIQUE_ID_FILE="/tmp/.ssh-UNIQUE_ID.$LOGNAME"

    if [ -f $SSH_UNIQUE_ID_FILE ]
    then
        TMUX_NAME=`cat $SSH_UNIQUE_ID_FILE`
        TMUX_NAME=`expr $TMUX_NAME + $RANDOM % 100`
    else
        TMUX_NAME=`expr $RANDOM % 1024`
    fi

    echo $TMUX_NAME > $SSH_UNIQUE_ID_FILE

    TMUX_NAME="id$TMUX_NAME"
fi

echo Connecting to tmux $TMUX_NAME on hostname $SSH_HOSTNAME

SLEEP=0
while true; do

    ssh $PORT -o TCPKeepAlive=no -o ServerAliveInterval=15 -Y -X -C -t -o BatchMode=yes $SSH_HOSTNAME "tmux attach-session -t $TMUX_NAME || tmux -2 -u new-session -s $TMUX_NAME"
    SLEEP=10
    if [ $SLEEP -gt 0 ]
    then
        echo Reconnecting to session $TMUX_NAME on hostname $SSH_HOSTNAME in $SLEEP seconds
        sleep $SLEEP
    fi
done
Neil McGill
quelle
1

Dies ist derjenige, der tatsächlich eine großartige Benutzererfahrung schafft. Es startet tmux automatisch, wenn Sie das Terminal öffnen (sowohl physisch als auch ssh). Sie können Ihre Arbeit an einem Gerät beginnen, das Terminal verlassen und auf dem anderen fortfahren. Wenn jemand erkannt wird, der bereits mit der Sitzung verbunden ist, wird eine neue Sitzung erstellt. Stellen Sie es auf den Server , abhängig von Ihrer Shell ~/.zshrcoder ~/.bashrc.

 if [[ -z "$TMUX" ]] ;then
     ID="$( tmux ls | grep -vm1 attached | cut -d: -f1 )" # get the id of a deattached session
     if [[ -z "$ID" ]] ;then # if not available attach to a new one
         tmux new-session
     else
         tmux attach-session -t "$ID" # if available attach to it
     fi
fi
Stanislaw Baranski
quelle
0

Ich weiß, dass ich einen alten Thread wiederbelebe, aber ich habe einige Arbeiten an der bashrc-Lösung durchgeführt und ich denke, dass sie eine Verwendung hat:

#attach to the next available tmux session that's not currently occupied
if [[ -z "$TMUX" ]] && [ "SSH_CONNECTION" != "" ];
then
    for i in `seq 0 10`; do #max of 10 sessions - don't want an infinite loop until we know this works
            SESH=`tmux list-clients -t "$USER-$i-tmux" 2>/dev/null` #send errors to /dev/null - if the session doesn't exist it will throw an error, but we don't care
            if [ -z "$SESH" ] #if there's no clients currently connected to this session
            then
                tmux attach-session -t "$USER-$i-tmux" || tmux new-session -s "$USER-$i-tmux" #attach to it
                break #found one and using it, don't keep looping (this will actually run after tmux exits AFAICT)
            fi #otherwise, increment session counter and keep going
    done

fi

Derzeit gibt es eine Obergrenze von 10 (11) Sitzungen - ich wollte meinen Server nicht mit einer Endlosschleife in bashrc beenden. Es scheint ziemlich zuverlässig zu funktionieren, abgesehen von dem Fehler, dass tmux auf Listen-Clients fehlschlägt, wenn die Sitzung nicht existiert.

Brydon Gibson
quelle
0

Auf diese Weise können Sie die Verbindung zu einer alten tmux-Instanz wiederherstellen, wenn Ihre SSH-Sitzung unterbrochen wird. Das execspart natürlich eine Gabel.

if [ -z "$TMUX"  ]; then
  pid=$(tmux ls | grep -vm1 "(attached)" | cut -d: -f1)
  if [ -z "$pid" ]; then
    tmux new -d -s $pid
  fi

  exec tmux attach -t $pid
fi
Ericcurtin
quelle