Wie kann ich ein Skript sofort nach dem Herstellen einer Verbindung über SSH ausführen?

24

Ich fing an, diese Frage zu stellen, beantwortete sie aber, während ich sie offen hatte. Ich werde diese Frage posten, meine Lösung weiterverfolgen und sie für andere mögliche Lösungen offen lassen.

<Hintergrundgeschichte>

Ich bin ein tmux und vim Benutzer. Ich mag Remote-Vim-Arbeit, da ich mir keine Sorgen machen muss, dass Ubuntu-Entwicklungsmaschinen ausfallen, wenn ein Flash-Film mich in Panik versetzt. Das Ausführen von tmux bedeutet, dass nach dem Neustart offene Dateien auf mich warten und ich dort weitermachen kann, wo ich aufgehört habe. Ich hatte Probleme mit der Ausführung von vim in einer tmux-Sitzung, wenn ich mich wie folgt verbinde:

ssh example.com -t 'tmux attach'

Es treten UTF-8-Probleme auf, die beim normalen Einspielen und beim manuellen Anhängen an eine tmux-Sitzung nicht auftreten.

</Hintergrundgeschichte>

Ich möchte also eine wiederverwendbare Methode zum Starten von etwas bei ssh login, die sich nicht auf andere Dinge auswirkt, die ich in meinem .zshrc(oder Ihrem, .bashrcwenn Sie immer noch bash verwenden) konfiguriert habe und die möglicherweise für meine Entwicklungsumgebung erforderlich sind erscheinen, wenn ich gelegentlich vor Ort an der genannten Maschine arbeite.

connrs
quelle

Antworten:

13

Beim Ausführen ssh example.comstartet der ssh-Daemon eine Anmeldeshell für Sie und die Anmeldeshell liest Ihre ~/.profile(oder ~/.bash_profileoder ~/.zprofileoder ~/.loginabhängig von Ihrer Anmeldeshell). Wenn Sie einen Befehl angeben, der remote ausgeführt werden soll (mit oder ohne -t), startet der ssh-Daemon eine gewöhnliche Shell, sodass Ihre .profilenicht gelesen wird. Abhilfe:

ssh example.com -t '. /etc/profile; . ~/.profile; tmux attach'

Die meisten ssh-Daemons sind so konfiguriert, dass die Übertragung von Umgebungsvariablen mit Ausnahme von abgelehnt wird LC_*. Wenn der SSH - Daemon auf example.comes erlaubt, können Sie eine benutzerdefinierte missbrauchen LC_*Variable automatisch gestartet tmux - diese in deinem ~/.profile:

if [ -n "$LC_tmux_session" ] && tmux has -t "$LC_tmux_session"; then
  exec tmux attach -t "$LC_tmux_session"
elif [ -n "${LC_tmux_session+1}" ] && tmux has; then
  exec tmux attach
fi

dann melde dich mit LC_tmux_session= ssh example.comoder an LC_tmux_session=session_name ssh example.com.

Diese Antwort enthält weitere Informationen zum Übergeben von Umgebungsvariablen an ssh.

Gilles 'SO - hör auf böse zu sein'
quelle
Der Grund, warum ich nicht benutze, ssh example.com -t 'tmux attach'liegt nicht darin, dass Probleme beim Laden meiner Umgebung auftreten, sondern darin, dass Probleme mit der UTF-8-Zeichenanzeige aufgetreten sind. Dieses Problem tritt nicht auf, wenn die Verbindung auf herkömmliche Weise hergestellt wird. Aus diesem Grund geht es bei dieser Frage um das Ausführen von Skripten unmittelbar nach dem Herstellen einer Verbindung über SSH.
Connrs
Ich liebe deine Lösung. Elegant
connrs
@connrs: Haben Sie Probleme mit UTF-8, auch wenn Sie Ihre ausführen .profile? Ich nahm die Frage falsch eingestellten locales auf dem Zielrechner zurückzuführen, die Ihre /etc/profileoder .profilefixiert. Das Problem mit dem Gebietsschema kann wahrscheinlich mit weiteren Informationen behoben werden.
Gilles 'SO - hör auf böse zu sein'
Ich wollte zurück ins Büro, um das zu testen. Sie haben vollkommen recht, wenn Sie die Datei / etc / profile verwenden, führt dies zu einem korrekten Verhalten. Sie haben jetzt tatsächlich das Problem gelöst, das mich dazu motiviert hat, diese allgemeinere Frage zu stellen
connrs
6

Ich habe zuvor empfohlen, PermitUserEnvironment yeseine Umgebungsvariable in Ihrer zu setzen und hinzuzufügen, ~/.ssh/environmentbis Eli Heady mit einem besseren Vorschlag in den Kommentaren unten eingewechselt ist .

Öffne deine .zlogin(bash: .bash_profileetc.) und schreibe folgendes:

if [[ "$SSH_CONNECTION" != "" && "$MY_SSH_CONNECTION" != "yes" ]]; then
    while true; do
        echo -n "Do you want to attach to a tmux session? [y/n]"
        read yn
        case $yn in
            [Yy]* ) MY_SSH_CONNECTION="yes" tmux attach; break;;
            [Nn]* ) break;;
            * ) echo "Please answer y/n";;
        esac
    done
fi

Inspiration: Wie fordere ich in einem Linux-Shell-Skript zur Eingabe auf?

Beachten Sie, dass ich die .zloginDatei verwendet habe, aber Sie können Ihre .zshrcDatei verwenden, aber ich möchte meine Punktedateien aufgeräumt halten und sie trennen, damit ich sie auf anderen Computern verwenden kann.

Ersetzen Sie die Frage durch etwas Passendes und ersetzen Sie sie MY_SSH_CONNECTION="yes" tmux attachdurch das, was Sie an diesem Punkt ausführen möchten.

Beachten Sie, wie das Skript MY_SSH_CONNECTION="yes"zuvor festgelegt wurde tmux attach, um es an tmux weiterzuleiten, da es auch eine Shell öffnet, die auf dasselbe Skript wie oben zugreift und eine Rekursion verhindert.

connrs
quelle
2
Die Verwendung von PermitUserEnvironment ist in einigen Umgebungen aufgrund möglicher Sicherheitsrisiken nicht möglich. SSH legt die Variable $ SSH_CONNECTION fest, die anstelle von $ SSH_LOGIN in Ihrem .zlogin verwendet werden kann, um die Verwendung von ~ / .ssh / environment zu vermeiden. So etwas if [[ "$SSH_CONNECTION" != "" ]]sollte es tun.
Eli Heady
3

Ich selbst füge dies zu meinen .bash_profile-Dateien hinzu:

if [ -z "$STY" ]; then
    reattach() { exec screen -A -D -RR ${1:+"$@"} ; }
fi
if [ -t 0 ]; then
    screen -wipe
    echo 'starting screen... (type Ctrl-C to abort)'
    sleep 5 && reattach
fi

Dadurch habe ich etwas Zeit, um das erneute Anfügen oder Erstellen einer Bildschirmsitzung abzubrechen. Es funktioniert nicht mit den Formaten 'ssh system command' (die ~ /.* profile nicht aufrufen). Eine Shell-Funktion ist so eingerichtet, dass sie bei einem Abbruch erneut verbunden wird.

Arcege
quelle
Groß! Ich schaffte es, dies zu verbessern, indem ich stattdessen bashrc einfügte und dann in jedem neuen Bildschirmfenster - wenn ich zu .profile wechselte, funktionierte es einwandfrei.
Hugo
0

Sie könnten in Betracht ziehen, zu rennen

ssh remotehost -t screen -DR

und führen Sie dort Ihre Terminalsitzung aus. Sie können dann die Verbindung trennen ( ^A^D) und später wieder herstellen (auch von einem anderen Client). Das Problem mit der nicht interaktiven Initialisierung wird dadurch behoben, da der Bildschirm voll interaktive Terminalsitzungen beibehält (optional auch Anmelde-Shells, man screen(1) oder ^A?).

sehe
quelle
Wie in meiner Frage erwähnt, verwende ich zur Verwaltung meiner Sitzungen nicht GNU, sondern tmux. Und beim Laden mit habe -t 'tmux attach'ich Probleme mit vim, die normalerweise nicht vorhanden sind. Aus diesem Grund geht es bei der eigentlichen Frage eher darum, Skripte auf ssh connect auszuführen, als um die Bildschirm- / Sitzungsverwaltung. Entschuldigung für die
Unklarheit
Tut mir leid, Sie haben tmux erwähnt, aber es hat mir nichts bedeutet. Vielen Dank, dass Sie ein neues Tool erwähnt haben!
sehe
0

Um mit den UTF-8-Problemen speziell zu sprechen, wenn Sie hinzufügen

SendEnv LANG

Und $LANGist auf so etwas wie en_US.UTF-8auf dem lokalen Ende gesetzt und Ihr sshd auf dem entfernten Ende erlaubt die SendEnvDirektive (mit AcceptEnvin sshd_config), der tmux auf dem anderen Ende sollte es honorieren. Ich hatte dieses Problem eine Weile und es war schwierig, es zu beheben.

Chris W.
quelle
0

Wenn Sie möchten, dass es jedes Mal ausgeführt wird, wenn Sie eine Verbindung herstellen, können Sie es einfach auf dem Remotecomputer tmux attacham unteren Rand hinzufügen ~/.profile.

Linesarefuzzy
quelle