So aktualisieren Sie die Umgebungsvariablen des SSH-Agenten beim Anhängen an vorhandene tmux-Sitzungen automatisch

78

Ich versuche einen guten Weg zu finden, um den SSH-Agenten wiederherzustellen, wenn ich eine getrennte tmux-Sitzung wieder verbinde.

Die Ursache scheint zu sein, dass sich die Sitzung des SSH-Agenten ändert, die Umgebungsvariable aus der tmux-Sitzung jedoch nicht aktualisiert wird.

Wie kann ich dies automatisieren, bevor ich die Sitzung selbst anhänge? Da die Sitzung, an die ich anhänge, nicht immer eine Bash-Eingabeaufforderung enthält, kann ich es mir nicht leisten, etwas darin einzugeben. Es muss etwas sein, das ausgeführt werden muss, bevor die tmux-Sitzung erstellt oder angehängt wird.

Ein Beispiel für den Code, den ich ausführe, ist https://gist.github.com/ssbarnea/8646491 - ein kleiner SSH-Wrapper, der tmux verwendet, um persistem SSH-Verbindungen zu erstellen. Dies funktioniert recht gut, aber manchmal funktioniert der SSH-Agent nicht mehr, sodass ich ihn nicht mehr verwenden kann, um eine Verbindung zu anderen Hosts herzustellen.

Sorin
quelle
Sie sollten wahrscheinlich Pymkins Antwort als Antwort markieren.
David Sanders

Antworten:

80

Es gibt einen ausgezeichneten Kern von Martijn Vermaat, der Ihr Problem ausführlich behandelt, obwohl er für Bildschirmbenutzer gedacht ist. Deshalb passe ich ihn hier für tmux an.

Zusammenfassen:

  1. Erstellen ~/.ssh/rcSie , wenn es noch nicht vorhanden ist, und fügen Sie den folgenden Inhalt hinzu:

    #!/bin/bash
    
    # Fix SSH auth socket location so agent forwarding works with tmux
    if test "$SSH_AUTH_SOCK" ; then
      ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
    fi
    
  2. Lass es in tmux funktionieren, füge dies zu deinem hinzu ~/.tmux.conf:

    # fix ssh agent when tmux is detached
    setenv -g SSH_AUTH_SOCK $HOME/.ssh/ssh_auth_sock
    

Zusätzliche Arbeit ist erforderlich, wenn Sie die X11-Weiterleitung aktivieren möchten .

Pymkin
quelle
1
Bei der erneuten Verbindung mit tmux wird nicht auf das neueste ssh_auth_sock aktualisiert. Es bleibt bei demjenigen, der die Sitzung ursprünglich erstellt hat, sodass dies nicht funktioniert. Irgendwelche Ideen?
Bret
6
Ich musste ein set -g update-environment -rzu .tmux hinzufügen , damit dieser Prozess funktioniert. Ich habe auch einige Namespaces zur Erstellung von Socket-Links hinzugefügt: gist.github.com/bcomnes/e756624dc1d126ba2eb6
Bret
1
Ein Fehler mit dem vorherigen GIST wurde behoben: Hatte $ (Hostname) in $ HOSTNAME in den Dateien .screenrc und .tmux.conf geändert
Bret
2
@Bret Ihre Lösung funktioniert einwandfrei, wenn Sie sich von einer tmux-Sitzung trennen und dann die SSH-Verbindung schließen. Es funktioniert jedoch nicht, wenn Sie die SSH-Verbindung zwangsweise schließen und dennoch an eine TMXX-Sitzung angeschlossen sind (z. B. wenn Sie plötzlich die Netzwerkverbindung verlieren und die SSH-Verbindung mit [Shift ~] [Enter] schließen. Irgendwelche Ideen, was dies beheben könnte?
Andrii Yurchuk
2
Nein, ich habe es leider aufgegeben.
Bret
39

Während Variablen standardmäßig tmux aktualisiert SSH werden, ist dies nicht erforderlich

  • Socket-Pfad ändern / hinzufügen
  • Ändern Sie die SSH_AUTH_SOCKETVariable

Ich mag die Lösung von Chris Down, die ich geändert habe, um eine Funktion hinzuzufügen

fixssh() {
    eval $(tmux show-env    \
        |sed -n 's/^\(SSH_[^=]*\)=\(.*\)/export \1="\2"/p')
}

in ~/.bashrc. Anruf fixsshnach dem Anhängen der Sitzung oder vor ssh/ scp/ rsync.

Neuere Versionen der tmuxSupport- -sOption für show-env, also nur

eval $(tmux show-env -s |grep '^SSH_')

ist möglich.

Hans Ginzel
quelle
Vielen Dank, das hat bei mir funktioniert! :) Ein kleines Problem: Wenn Sie dies in einem wieder angebrachten tmux-Bereich tun, funktioniert es nicht. Ich muss den alten Bereich schließen und einen neuen öffnen. Eine Lösung hierfür besteht darin, tmux zu trennen, die $DISPLAYVariable anzuzeigen, tmux erneut zuzuordnen und $DISPLAYin meinem Fall korrekt einzustellen export DISPLAY=localhost:14.0, aber die Anzahl scheint sich bei jeder ssh-Sitzung zu ändern.
PlasmaBinturong
"Während tmux SSH-Variablen standardmäßig aktualisiert" Worüber sprechen Sie? (Ich vermute, dass der Anker in Ihrem Link jetzt nicht mehr vorhanden ist.
Bruno Bronosky
1
@BrunoBronosky Ich habe seinen Link repariert. Sie hatten Recht: Anker existierte nicht mehr. Scheint jetzt eine stabile Form zu haben.
Überdenken Sie den
Dies sollte die beste Antwort sein. Es ist nicht erforderlich, eine neue temporäre Datei zu erstellen.
Sjy
24

Folgendes verwende ich zum Aktualisieren SSH_AUTH_SOCKin einem tmuxFenster (basierend auf Hans Ginzels Skript):

alias fixssh='eval $(tmux showenv -s SSH_AUTH_SOCK)'

Oder dafür tmuxhat nicht showenv -s:

alias fixssh='export $(tmux showenv SSH_AUTH_SOCK)'
user1338062
quelle
6

Hier ist meine Lösung, die beide Ansätze umfasst und keine zusätzliche Eingabe erfordert, wenn ich mich wieder mit der tmux-Sitzung verbinde

alias ssh='[ -n "$TMUX" ] && eval $(tmux showenv -s SSH_AUTH_SOCK); /usr/bin/ssh'
Max
quelle
1
Es sieht so aus, als würde es eval $(tmux showenv -s SSH_AUTH_SOCK)lokal und nicht remote ausgeführt!
Acgtyrant
Ich habe dies auf der Fernbedienung geschrieben (tmux läuft) und es hat wie erwartet funktioniert. Vielen Dank!
Riywo
4

Hier gibt es viele gute Antworten. Aber es gibt Fälle, in denen tmux show-environmentnicht gesehen wird SSH_AUTH_SOCK. In diesem Fall können Sie findes explizit suchen.

export SSH_AUTH_SOCK=$(find /tmp -path '*/ssh-*' -name 'agent*' -uid $(id -u) 2>/dev/null | tail -n1)

Das ist lang und kompliziert, also werde ich es aufschlüsseln ...

01  export SSH_AUTH_SOCK=$(
02    find /tmp \
03      -path '*/ssh-*'
04      -name 'agent*'
05      -uid $(id -u)
06      2>/dev/null
07    | tail -n1
08  )
  1. exportDie SSH_AUTH_SOCKUmgebungsvariable, die auf die Ausgabe der $()Befehlssubstitution gesetzt ist
  2. find Dateien, die in beginnen /tmp
  3. Beschränken Sie die Ergebnisse nur auf diejenigen mit /ssh-im Pfad
  4. Beschränken Sie die Ergebnisse nur auf diejenigen, deren Name mit beginnt agent
  5. Beschränken Sie die Ergebnisse auf diejenigen, deren Benutzer-ID mit dem aktuellen Benutzer übereinstimmt
  6. Alle (Berechtigungen usw.) Fehler zum Schweigen bringen
  7. Nimm nur das letzte Ergebnis, wenn es mehrere gibt

Sie können möglicherweise 6 & 7 weglassen, wenn Sie wissen, dass es nur 1 Ergebnis gibt und Sie sich nicht für stderr-Müll interessieren.

Bruno Bronosky
quelle
1
Von allen hier aufgeführten Lösungen funktionierte nur dies auf dem Mac.
SilentGuy
Schön, aber es kann erforderlich sein, nur den LETZTEN SSH-Agent-Socket zu verwenden. Dazu können wir eine Sortierung hinzufügen in find:find /tmp -path '*/ssh-*' -name 'agent*' -uid (id -u) -printf "%T+\t%p\n" 2>/dev/null | sort | tail -n1 | awk -F'\t' '{print $2 }'
ColCh
3

Ich verwende eine Variation der vorherigen Antworten:

eval "export $(tmux show-environment -g SSH_AUTH_SOCK)"

Angenommen, Sie haben den SSH-Agenten von der äußeren Umgebung aus gestartet. Gleiches gilt für andere Umgebungsvariablen wie DISPLAY.

Raffi
quelle
Sind Sie sicher, dass dies für Sie funktioniert? Mit -gbekomme ich den abgestandenen Wert von $SSH_AUTH_SOCK. Weggehen -gmacht den Trick. Siehe auch andere Antworten.
Feklee
1

Ich ziehe es vor, die Konfiguration von TMUX (usw.) zu vermeiden und alles rein zu behalten ~/.ssh/. Auf dem Remote- System:

Erstellen ~/.ssh/rc:

#!/bin/bash

# Fix SSH auth socket location so agent forwarding works within tmux
if test "$SSH_AUTH_SOCK" ; then
  ln -sf $SSH_AUTH_SOCK ~/.ssh/ssh_auth_sock
fi

Fügen Sie Folgendes hinzu, ~/.ssh/configdamit es nicht mehr darauf angewiesen ist $SSH_AUTH_SOCK, was in freistehenden Terminals veraltet ist:

Host *
  IdentityAgent ~/.ssh/ssh_auth_sock

Bekannte Einschränkungen

  • ssh-addwird nicht verwendet ~/.ssh/configund kann daher nicht mit kommunizieren ssh-agent. Befehle wie ssh-add -lerzeugen Fehler, obwohl sie gut ssh user@hostfunktionieren, ebenso wie das Aktualisieren von Git-Fernbedienungen, auf die über SSH zugegriffen wird.
RobM
quelle
1

Möglicherweise habe ich eine Lösung ausgearbeitet, die vollständig in der ~/.tmux.confKonfigurationsdatei enthalten ist. Es ist ein anderer Ansatz als das Ändern des ~/.bash_profileund ~/.ssh/rc.

Lösung nur mit ~/.tmux.conf

Schneiden Sie einfach den folgenden Code aus und fügen Sie ihn in Ihren ein ~/.tmux.conf

# ~/.tmux.conf

# SSH agent forwarding
#
# Ensure that SSH-Agent forwarding will work when re-attaching to the tmux
#   session from a different SSH connection (after a dropped connection).
#   This code will run upon tmux create, tmux attach, or config reload.
#
# If there is an SSH_AUTH_SOCK originally defined:
#   1) Remove all SSH related env var names from update-environment.
#      Without this, setenv cannot override variables such as SSH_AUTH_SOCK.
#      Verify update-environment with: tmux show-option -g update-environment
#   2) Force-set SSH_AUTH_SOCK to be a known location
#      /tmp/ssh_auth_sock_tmux
#   3) Force-create a link of the first found ssh-agent socket at the known location
if-shell '[ -n $SSH_AUTH_SOCK ]' " \
  set-option -sg update-environment \"DISPLAY WINDOWID XAUTHORITY\"; \
  setenv -g SSH_AUTH_SOCK /tmp/ssh_auth_sock_tmux; \
  run-shell \"ln -sf $(find /tmp/ssh-* -type s -readable | head -n 1) /tmp/ssh_auth_sock_tmux\" \
"

Vorbehalt

Die obige Lösung ist zusammen mit den anderen Lösungen anfällig für eine Race-Bedingung, wenn mehrere Verbindungen zu derselben Maschine hergestellt werden. Bedenken Sie:

  • Client 1 Verbinden: SSH mit machineX, tmux starten / anhängen ( ssh_auth_sockLink schreiben )
  • Client 2 Connect: SSH an machineX, tmux starten / anhängen ( ssh_auth_sockLink überschreiben )
  • Client 2 trennen: Client 1 hat einen veralteten ssh_auth_sockLink, wodurch er unterbrochen wirdssh-agent

Diese Lösung ist jedoch etwas widerstandsfähiger, da sie den ssh_auth_sockLink nur beim Starten / Anhängen von tmux überschreibt , anstatt beim Initialisieren einer Bash-Shell ~/.bash_profileoder einer SSH-Verbindung~/.ssh/rc

Um diese letzte Racebedingung abzudecken, kann eine Schlüsselbindung hinzugefügt werden, um die tmux-Konfiguration mit einer (Ctrl-b r)Schlüsselsequenz neu zu laden .

# ~/.tmux.conf

# reload config file
bind r source-file ~/.tmux.conf

Wenn Sie diese Sequenz innerhalb einer aktiven tmux-Sitzung ausführen, wenn die ssh_auth_sockVerbindung veraltet ist, wird die SSH-Agent-Verbindung aktualisiert .

David W.
quelle
0

Nachdem ich auf so viele Vorschläge gestoßen war, fand ich endlich eine Lösung, mit der TMUX den veralteten SSH-Agenten nach dem Anhängen aktualisieren kann. Grundsätzlich müssen sowohl die zshrc-Dateien auf dem lokalen als auch auf dem Remotecomputer geändert werden.

Fügen Sie die folgenden Codes in das lokale zshrc ein, das auf dieser Referenz basiert .

export SSH_AUTH_SOCK=~/.ssh/ssh-agent.$(hostname).sock
ssh-add -l 2>/dev/null >/dev/null
# The error of executing ssh-add command denotes a valid agent does not
# exist. 
if [ $? -ge 1 ]; then
  # remove the socket if it exists
  if [ -S "${SSH_AUTH_SOCK}" ]; then
    rm "${SSH_AUTH_SOCK}"
  fi
  ssh-agent -a "${SSH_AUTH_SOCK}" >/dev/null
  # one week life time
  ssh-add -t 1W path-to-private-rsa-file
fi

Fügen Sie den folgenden Code in das Remote-zshrc ein, an das die tmux-Sitzung angehängt wird.

alias fixssh='eval $(tmux showenv -s SSH_AUTH_SOCK)'

Dann ssh in die entfernte Maschine. Die Option -A ist erforderlich.

ssh -A username@hostname

Hängen Sie die TMUX-Sitzung an. Überprüfen Sie die TMUX-Umgebungsvariablen

# run this command in the shell
tmux showenv -s
# or run this command after prefix CTRL+A or CTRL+B
:show-environment

Führen Sie es fixsshin den zuvor vorhandenen Bereichen aus, um den SSH-Agenten zu aktualisieren. Wenn ein neuer Bereich erstellt wird, wird automatisch der neue SSH-Agent abgerufen.

David Li
quelle