Aus Linux-Magazin 04/2015

SSH-Umgebung ausrollen

© Jasmin Merdan, 123RF

Will sich ein Admin auf fremden Rechnern stets heimisch fühlen, nimmt er seine gewohnte SSH-Arbeitsumgebung einfach mit. Das klappt auch, wenn er ständig viele neue Server besuchen muss, etwa in der Cloud. Bash-Skripte machen es möglich.

Trotz aller Automation bleibt die Konsole das wichtigste Werkzeug aller Linux-Admins, meist im Fernzugriff über SSH. Zum vielleicht zweitwichtigsten Begleiter wird die richtige Konfiguration der Arbeitsumgebung und der Shelltools. Egal ob es um Farben, Abkürzungen, Vim-Konfigurationen oder Skriptsammlungen geht – sie alle stecken oft in diversen Dateien im Homeverzeichnis.

Erfahrene Admins kopieren daher im ersten Schritt beim Besuch eines neuen Servers ihre Arbeitsumgebung auf ihn. Andere wiederum verwenden die Softwareverteilung, um bei Updates auch gleich die Homeverzeichnisse der Admin-Benutzer zu streuen.

Doch steigt die Anzahl der betreuten Server oder kommen ständig neue hinzu – etwa in der Cloud –, skalieren diese Lösungen schlecht. Der Admin müsste seine Zielserver vor fast jeder SSH-Sitzung manuell vorbereiten. Verwendet er hingegen eine Softwareverteilung, gibt gewöhnlich der allgemeine Update-Rhythmus vor, wie oft der Server seine Arbeitsumgebung aktualisiert. Eher selten ergibt es Sinn, wegen einer kleinen Änderung in der ».bashrc« sämtliche Server zu aktualisieren.

Reiseplanung

Das Problem stellt den Serververwalter also vor drei grundsätzliche Herausforderungen. Zunächst möchte er, dass die Änderungen an den Dateien der persönlichen Arbeitsumgebung immer dort verfügbar sind, wo er gerade arbeitet. Zweitens sollen die Aktualisierungen unabhängig von allen anderen Prozessen im Rechenzentrum erfolgen. Drittens muss die Lösung auch noch mit einer beliebigen Anzahl an Servern und Admins skalieren – darf also nicht zum Flaschenhals werden.

Diese Kombination von Anforderungen gibt dann auch den Rahmen für eine Lösung vor:

  • Der Admin überträgt seine persönliche Arbeitsumgebung am besten im Zuge einer gewöhnlichen Wartungsarbeit und koppelt sie beispielsweise an die SSH-Verbindungen, mit denen er arbeitet.
  • Jede neue SSH-Verbindung sollte auch die Arbeitsumgebung aktualisieren, um zu gewährleisten, dass der Admin stets mit aktuellen Dateien hantiert.

Gepäck inklusive

Die zwei kleinen Shellskripte im Paket »ssh-personal-environment« [1] stellen eine Lösung bereit, die diesen Anforderungen entspricht. SSH reicht die Dateien der persönlichen Arbeitsumgebung mit Hilfe von Umgebungsvariablen an den Server durch (Abbildung 1). Die Spracheinstellungen wechseln auf demselben Pfad die Seite. Damit stehen diese Inhalte zu jeder SSH-Sitzung bereit, ohne dass der Verwalter ein weiteres Kommando ausführen oder eine zusätzliche SSH-Verbindung aufbauen muss.

Abbildung 1: In einer Umgebungsvariablen verpackt überträgt die SSH-Verbindung die persönliche Arbeitsumgebung.

Abbildung 1: In einer Umgebungsvariablen verpackt überträgt die SSH-Verbindung die persönliche Arbeitsumgebung.

In der Praxis funktioniert es so, dass sich der Nutzer wie gewohnt per SSH auf einem anderen Server anmeldet und dort automatisch seine persönliche Arbeitsumgebung vorfindet. Abbildung 2 zeigt, wie es aussieht, wenn SSH zum Beispiel den farbigen Shellprompt von einem Ubuntu-Desktop auf einen Centos-Server überträgt.

Abbildung 2: Die Shell auf dem Zielsystem benutzt bereits die ».bashrc« aus der persönlichen Arbeitsumgebung. Der Debugmodus zeigt, was die Skripte machen.

Abbildung 2: Die Shell auf dem Zielsystem benutzt bereits die ».bashrc« aus der persönlichen Arbeitsumgebung. Der Debugmodus zeigt, was die Skripte machen.

Reiseroute

Auf der Seite des SSH-Clients platziert dabei die Bash-Funktion »update_ssh_personal_environment()« die Umgebungsvariable »SSH_PERS_ENV_DATA« in einem Base64-kodierten Tar.gz-Archiv (Listing 1 und Abbildung 3). Über die Variable »SSH_PERS_ENV_FILES« konfiguriert der Nutzer, welche Dateien er aus dem Homeverzeichnis automatisch verpacken und übermitteln möchte.

Listing 1

update_ssh_personal_environment.sh

01 update_ssh_personal_environment() {
02     if [ $# -gt 0 -a "$1" = "--debug" ] ; then
03         export SSH_PERS_ENV_DEBUG=1
04         shift
05     fi
06     if test -n "$SSH_PERS_ENV_FILES" -o "$#" -gt 0  ; then
07         export SSH_PERS_ENV_FILES=$(
08             eval echo $@ $SSH_PERS_ENV_FILES | \
09                 tr " " "\n" | \
10                 sort -u | \
11                 tr "\n" " "
12         ) # pattern expansion
13         test "${SSH_PERS_ENV_DEBUG:-}" && \
14             echo "Packing as SSH Personal Environment: $SSH_PERS_ENV_FILES" 1>&2
15         export SSH_PERS_ENV_DATA=$(tar -C ~ -cz $SSH_PERS_ENV_FILES | base64)
16     fi
17 }
Abbildung 3: Die Lösung benutzt drei Umgebungsvariablen. In »SSH_PERS_ENV_DATA« ist ein Base64-kodiertes Tar.gz-Archiv mit den Nutzdaten enthalten.

Abbildung 3: Die Lösung benutzt drei Umgebungsvariablen. In »SSH_PERS_ENV_DATA« ist ein Base64-kodiertes Tar.gz-Archiv mit den Nutzdaten enthalten.

Die Variable setzt er zum Beispiel in der ».bashrc« oder ».bash_aliases« , sie enthält eine Liste von Dateien oder Ordnern im Homeverzeichnis. Bei Bedarf kann er in der Liste auch Muster verwenden, beispielsweise

SSH_PERS_ENV_FILES=".bash* .vim*"

um sämtliche Bash- und Vim-Konfigurationen mitzunehmen.

Übergibt der SSH-Anwender beim Aufruf von »update_ssh_personal_environment.sh« noch mehrere Dateien, Verzeichnisse oder Pattern als Parameter, landen sie zwar in der »SSH_PERS_ENV_FILES« -Liste, allerdings nur temporär. Auf diesem Wege kann er mit verschiedenen Optionen experimentieren, ohne sie fest in die »SSH_PERS_ENV_FILES« -Liste einzutragen.

Über eine »–debug« -Option schaltet er zudem Debug-Ausgaben an. Die SSH-Verbindung überträgt dann die Option über die Umgebungsvariable »SSH_PERS _ENV_DEBUG« .

Empfangskomitee

Auf der Seite des SSH-Servers hängt sich das Skript »/etc/ssh/sshrc« in jede SSH-Verbindung ein und entpackt die über die »SSH_PERS_ENV_DATA« -Variable empfangenen Daten ins Homeverzeichnis (Listing 2). Weil zudem der Server das »sshrc« -Skript vor der Login-Shell des Benutzers ausführt, kann er dabei auch gleich Dateien wie die ».bashrc« ausliefern.

Listing 2

/etc/ssh/sshrc

01 if which xauth >/dev/null 2>&1 && read proto cookie && test "$DISPLAY" ; then
02         if test "$(expr substr "$DISPLAY" 1 10)" = localhost: ; then
03                 # X11UseLocalhost=yes
04                 echo add unix:"$(expr substr "$DISPLAY" 11 99)" $proto $cookie
05         else
06                 # X11UseLocalhost=no
07                 echo add "$DISPLAY" $proto $cookie
08         fi | xauth -q -
09 fi
10
11 # unpack personal environment
12 if test "$SSH_PERS_ENV_DATA" ; then
13      test "$SSH_PERS_ENV_DEBUG" && echo "Unpacking SSH Personal Environment Data..."
14      echo "$SSH_PERS_ENV_DATA" | base64 -d | tar ${SSH_PERS_ENV_DEBUG:+-v} -xzC ~
15 fi

Über die SSH-Verbindung lassen sich auf diesem Wege mindestens 100 KByte an Nutzdaten (je nach Kompression auch deutlich mehr) übertragen, was selbst für umfangreiche selbst gebaute Konfigurationsdateien und Skriptsammlungen genügen sollte.

Listing 3

determine_maximum_transfer_size.sh

01 #!/bin/bash
02 set -e -E -u
03 #
04 # given a remote user@host with ssh-personal-environment installed, determine the maximum amount of random
05 # data that can be transferred via the environment variables.
06
07 TARGET="$1" ; shift
08
09 data_file=$(mktemp)
10 data_filename=${data_file##*/}
11 data_dirname=${data_file%/*}
12 trap "rm -f $data_file" 0
13
14 unset SSH_PERS_ENV_DEBUG
15
16 lastsize=0
17 for size in $(eval echo {${MIN:=10}..${MAX:=150}..${STEP:=10}}) ; do
18         dd if=/dev/urandom bs=1k count="$size" of="$data_file" status=none
19         checksum=( $(md5sum "$data_file") )
20
21         echo "TESTING $size KB"
22         remote_checksum=( $(
23                 export SSH_PERS_ENV_DATA=$(tar -C "$data_dirname" -cz "$data_filename" | base64)
24                 ssh "$TARGET" md5sum "$data_filename" \; rm -f "$data_filename" 2>/dev/null || echo FAILED
25                 ) )
26         if [[ $checksum != $remote_checksum ]] ; then
27                 echo "FAILED to transfer $size KB, safe size is $lastsize KB"
28                 exit 0
29         fi
30         let lastsize=size
31 done

Das Skript »determine_maximum_transfer_size.sh« aus Listing 3 ermöglicht es dem Admin, den genauen Wert auf dem eigenen System zu bestimmen. So sieht das Skript schließlich in Aktion aus:

$ MIN=90 STEP=1 ./determine_maximum_transfer_size.sh ubuntu@server.com
TESTING 90 KB
TESTING 91 KB[...]
TESTING 95 KB
FAILED to transfer 95 KB, safe size is 94 KB

Damit SSH-Client und -Server die Umgebungsvariablen tatsächlich übertragen, legt der Admin auf Quell- und Zielrechner noch Hand an die SSH-Konfiguration. In der Konfigurationsdatei »/etc/ssh/ssh_config« aktiviert er auf dem Client die Variablenübertragung:

SendEnv SSH_PERS_ENV_DATA SSH_PERS_ENV_FILES SSH_PERS_ENV_DEBUG

Auf dem SSH-Server kommt in »/etc/ssh/sshd_config« das passende Gegenstück zum Tragen:

AcceptEnv SSH_PERS_ENV_DATA SSH_PERS_ENV_ FILES SSH_PERS_ENV_DEBUG

Aus den Quellen auf der Heft-DVD lässt sich über »make deb« übrigens ein Debian-Paket bauen, das die Skripte enthält und auch die SSH-Konfiguration anpasst. Ist das »ssh-personal-environment« -Paket überall installiert, findet der Admin auf jedem System seine persönliche Arbeitsumgebung vor und kann damit effizienter arbeiten [2]. (kki)

Infos

  1. Skripte und Pakete zu »ssh-personal-environment« : https://github.com/schlomo/ssh-personal-environment
  2. Ursprünglicher Blogeintrag zum Thema: http://blog.schlomo.schapiro.org/2014/02/ssh-with-personal-environment.html
DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 3 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Nach oben