iTerm2 und SSH - oder: Bin ich auf dem richtigen Server?

    Sebastian Kurfürst20.12.2021

    UPDATE August 2022: Es gibt einen Teil 2 dieses Blogbeitrages, der eine verbesserte Lösung darstellt.

    Ich hatte schon hin und wieder das Problem, dass ich einige SSH-Verbindungen auf andere Systeme offen hatte, und ausversehen auf dem falschen System einen Befehl ausgelöst habe. Meist geht so etwas glimpflich ab, aber ich habe auch schon auf diesem Weg einiges an Schaden angerichtet. Was kann man also tun, um dieses Problem zu reduzieren?

    Ich wusste schon länger, dass iTerm2 diverse Anpassungsmöglichkeiten hat - allerdings habe ich nur diverse Lösungen gefunden, die Scripte auf der Remote-Seite (also auf den SSH-Servern) benötigen würden. Mir war aber wichtig, dass es eine rein client-seitige Lösung ist. Ich bin vor kurzem durch Zufall auf diesen Blog Post von Ivan Drinchev gestoßen - und die hier dargestellte Lösung ist an seinem Beispiel orientiert.

    Das Ziel: visuell erkennen, auf welchem System man sich befindet

    Mit wenigen Schritten sieht das Ergebnis so aus wie unten gezeigt: Beim SSH Login färbt sich der Terminal-Tab magenta, und die IP-Adresse des Systems ist auch dargestellt.

    KI generiert: Das Bild zeigt ein Terminalfenster auf einem Computerbildschirm mit einem Verzeichnis- und Branchennamen. Der Benutzer befindet sich in einer Git-Umgebung auf der Branch "feature/180-postgresGraph".

    Grundprinzip: iTerm2 Escape Codes und Badges

    iTerm2 unterstützt sogenannte Escape Codes, d.h. bestimmte Terminal-Ausgabe, welche dann eine Änderung in iTerm selbst nach sich zieht. Auf diese Weise kann man bspw. den Tab-Hintergrund umfärben, oder aber einen Badge Text einstellen. Probiert es mal mit den Befehlen unten aus!

    2. Befehle beim SSH Connect

    3. Reset, wenn die SSH-Verbindung vorbei ist

    Zusätzlich nutzen wir überall nutzerbasierte Public Key SSH-Logins, wo man dann mittels sudo su - zum Root-User wechseln kann. Dabei muss man dann nochmals das eigene, serverspezifische Passwort eingeben. Auf diesem Wege hat man die doppelte Kontrolle, dass man wirklich auf dem richtigen Server unterwegs ist.

    # set red-part of tab color to 255 -> red echo "\033]6;1;bg;red;brightness;255\a" # set red-part of tab color to 100 -> dark red echo "\033]6;1;bg;red;brightness;255\a" # set green-part of tab color to 50 -> brown (red + green) echo "\033]6;1;bg;red;brightness;50\a" # reset to default echo "\033]6;1;bg;*;default\a" # set "Badge" (background) printf "\e]1337;SetBadgeFormat=%s\a" $(echo -n "Hallo" | base64) # reset badge printf "\e]1337;SetBadgeFormat=\a"

    Befehle beim SSH Connect

    Jetzt müssen wir dafür sorgen, dass diese Befehle beim SSH Connect ausgeführt werden. Hierfür ist die SSH-Konfigurationsoption LocalCommand geeignet. Aus der Manpage von SSH:

    LocalCommand: Specifies a command to execute on the local machine after successfully connecting to the server. The command string extends to the end of the line, and is executed with the user's shell. The following escape character substitutions will be performed: '%d' (local user's home directory), '%h' (remote host name), '%l' (local host name), '%n' (host name as provided on the command line), '%p' (remote port), '%r' (remote user name) or '%u' (local user name). This directive is ignored unless PermitLocalCommand has been enabled.

    Das sieht schon ziemlich gut aus - jetzt benötigen wir nur noch einen Weg, am Ende einer SSH-Session die Overlays wieder rückgängig zu machen. Leider gibt es kein "LocalCommandEnd" oder etwas vergleichbares, weshalb wir hier etwas tricksen müssen.

    Reset, wenn die SSH-Verbindung vorbei ist - mit phook

    Dieser Trick und das dazugehörige Tool stammt aus dem Blog Post von Ivan Drinchev. Ein sehr eleganter Kniff, der diesen Reset ermöglicht: Wenn ein Prozess einen anderen Prozess startet, dann ist der gestartete Prozess standardmäßig der Kindprozess des Elternprozesses. So ist also das durch LocalCommand ausgeführte Kommando der Kindprozess des SSH-Kommandos.

    Das Tool phook überwacht nun den eigenen Parent-Prozess, und führt einen Befehl aus, wenn dieser gestoppt wird. Auf diesem Weg kann man also sagen: "beim Starten der SSH Verbindung tue das Eine, beim Stoppen das andere".

    Show me the code - wie richte ich das ein?

    iTerm2 installieren und nutzen. Dann phook über homebrew installieren: 

    brew install sandstorm/tap/phook

    als letztes in der ~/.ssh/config Datei folgende Zeilen einfügen:

    # ~/.ssh/config # NOTE: your git servers must come first and they need to DISABLE the local command, # as the output breaks git-over-SSH. Same for rsync. Host github.com PermitLocalCommand no Host gitlab.sandstorm.de PermitLocalCommand no # add your other Git servers as needed here. Host * # NOTE: for people using Yubikeys, the following line is already in your SSH config and needs to be KEPT there: # IdentityAgent /opt/homebrew/var/run/yubikey-agent.sock # Set the color to magenta, and the badge to the target host. PermitLocalCommand yes LocalCommand phook -e 'echo "\033]6;1;bg;red;brightness;255\a\033]6;1;bg;green;brightness;0\a\033]6;1;bg;blue;brightness;255\a";printf "\e]1337;SetBadgeFormat=%%s\a" $(echo "%n" | base64)' -a 'echo "\033]6;1;bg;*;default\a";printf "\e]1337;SetBadgeFormat=\a"'

    That's it :) Die badge-Farbe kann noch in den Einstellungen von iTerm2 -> Profiles -> Colors eingestellt werden.

    Habt ihr Feedback oder weitere tolle Tricks? Lasst es uns wissen :)

    Dein Besuch auf unserer Website produziert laut der Messung auf websitecarbon.com nur 0,28 g CO₂.