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.
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 :)