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

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?

Mein Ziel habe ich in einem vorherigen Blog Post schonmal beschrieben: visuell erkennen, auf welchem System man sich befindet.

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

SCR 20220818 Sty

In Teil 1 des Blog Posts habe ich das Grundprinzip beschrieben: Die Verwendung von Shell Escape Codes zum Einblenden von Overlays bei iTerm2.

Die skizzierte Lösung hatte jedoch mehrere gravierende Probleme, wenn andere Tools wie Git oder Ansible über SSH funktionieren mussten. Dabei musste jeder Git-Server, wie auch jeder Server der mit Ansible deployt werden sollte, explizit vom dargestellten Script ausgenommen werden, da das Script (durch das Injecten von Escapesequenzen) Fehler bei Git oder Ansible produziert hatte.

ssh config: Match

Nun bin ich vor einigen Tagen auf einen Blog Post gestoßen, wo die SSH-Config-Direktive Match erläutert wurde: Diese Einstellung ermöglicht es, eine Art "Konfigurations-Overlay" über die normale SSH-Konfiguration zu legen. Um zu entscheiden, ob der "Overlay" aktiviert oder deaktiviert ist, kann man ein beliebiges Script hinterlegen.

Nun hatte ich die Idee, in der Prozesshierarchie - ausgehend vom SSH-Prozess selbst - weiter "hoch" zu schauen (die Eltern des SSH-Prozesses, etc); um herauszufinden, ob der SSH-Befehl gerade im Kontext einer interaktiven Shell (in meinem Fall ZSH) oder in einem anderen Kontext wie Ansible oder Git ausgeführt wurde. Dies macht die Zeile:

ps p $(ps p $$ -o ppid | grep -v PPID) -o ppid | grep -v PPID | xargs -r ps ww | grep zsh

(das habe ich iterativ entwickelt; siehe unten 😉)

Konfiguration in .ssh/config:

Folgende Zeilen zeigen den aktuellen Host als Badge in iTerm2, und machen auch Ansible, Git, etc. nicht kaputt:

# If the SSH process is started from an interactive ZSH session, we display the badge of the target host. # # NOTE: # - the PARENT of the exec'd process is the SSH process itself # - the GRANDPARENT of the exec'd process is the calling process of the SSH process (e.g. ZSH, Ansible, Git) Match exec "ps p $(ps p $$ -o ppid | grep -v PPID) -o ppid | grep -v PPID | xargs -r ps ww | grep zsh" # 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"'

Viel Spaß damit!

PS: Entwicklung des Grandparent-Finder-Scripts

# output current process ID > echo $$ 56913 # output PARENT process ID as a table > ps p $$ -o ppid PPID 56912 # remove table heading -> Parent Process ID > ps p $$ -o ppid | grep -v PPID 56912 # GRANDparent Process ID (the above twice): > ps p $(ps p $$ -o ppid | grep -v PPID) -o ppid | grep -v PPID 7359 # load infos about the given process ID > echo 56912 | xargs -r ps ww PID TT STAT TIME COMMAND 56912 s009 Ss 0:00.01 /usr/bin/login -fpl sebastian /Applications/iTerm.app/Contents/MacOS/ShellLauncher --launch_shell # SIDENOTE: debugging what the resolved process is > ps p $(ps p $$ -o ppid | grep -v PPID) -o ppid | grep -v PPID | xargs -r ps ww > /tmp/foo # then look into /tmp/foo ######################################################################################### # THE FINAL LINE which checks whether the grandparent process is ZSH (not ansible, not Git). ps p $(ps p $$ -o ppid | grep -v PPID) -o ppid | grep -v PPID | xargs -r ps ww | grep zsh #########################################################################################