Session-Management mit »screen«
Inhalt
1. Einleitung
»screen« ist ein kleines Programm, das es ermöglicht, mehrere Sitzungen (Sessions) von einem einzigen Terminal laufen zu lassen. Es baut zu jeder Session ein virtuelles Fenster auf und verbindet sie zu einem tty. Die Session kann auch gänzlich vom Terminal getrennt werden (detach).
Im Zeitalter von grafischen Oberflächen ist es nicht mehr so interessant zwischen verschiedenen Sitzungen innerhalb
eines Terminals wechseln zu können - das Starten eines zweiten Terminalfensters (xterm, putty, ...) tut
es auch. Darum soll es in diesem Artikel daher auch gar nicht gehen. Vielmehr soll ein Session Management mit Hilfe
von »screen« aufgebaut werden.
2. »screen« installieren
Wer Linux nutzt, wird screen im Allgemeinen bereits vorfinden und es nicht installieren müssen. Falls es doch nicht installiert ist, findet sich ein Paket »screen« sicher auf der CD.
Bei proprietären Unix-Derivaten sieht die Sache anders aus, hier muss screen möglicherweise aus fremden Quellen installiert werden. Bei fehlender root-Berechtigung können Sie screen auch in Ihrem Heimatverzeichnis installieren. Dies soll am Beispiel AIX 5.3 exemplarisch durchgeführt werden:
Unter aixpdslib.seas.ucla.edu/packages/screen.html habe ich mir die entsprechende Version heruntergeladen und in meinem Heimatverzeichnis entpackt:
$ cd $ uncompress -c screen.4.0.2.tar.Z | tar xf - $ mv usr/local/* . $ rmdir usr/local $ rmdir usr
screen findet sich nun unter ~/bin/screen.
3. Grundlegende Kommandos
Eine neue Session lässt sich mit
screen [Kommando]starten. Für unsere Zwecke interessant ist der Aufbau einer ssh-Verbindung zu einem entfernten Rechner, also etwa
$ screen ssh barney
Eine so aufgebaute verbindung lässt sich mit der Tasten-Kombination <CRTL-A><D> vom Terminal abkoppeln, ohne dass die Shell dies bemerken würde.
Alle zur Zeit aktiven Sessions lassen sich mit dem Schalter »-list« anzeigen:
$ screen -list There are screens on: 401566.pts-18.darkstar (Detached) 159936.pts-12.darkstar (Attached) 2 Sockets in /tmp/uscreens/S-armin.
Abgekoppelte Sitzungen werden als (Detached) angezeigt. Bei einer größeren Anzahl abgekoppelter Sessions ist es aber schwierig, die richtige aus der Liste zu finden, da man sich kaum PID und tty gemerkt hat (darkstar ist nicht etwa der Name des Systems, zu dem die ssh-Verbindung aufgebaut wurde, sondern der Rechner, auf dem ich »screen« aufgerufen habe - folglich also immer derselbe...)
Deshalb gibt es die Möglichkeit, der Session einen eigenen Namen zu geben, der dann hinter dem PID auftaucht, also etwa...
$ screen -S barney ssh barney ^AD [detached]
$ screen -list There are screens on: 700572.pts-18.darkstar (Detached) 159936.pts-12.darkstar (Attached) 921688.barney (Detached) 3 Sockets in /tmp/uscreens/S-armin.
Nun ist klar, welchen Screen wir gerade in den Hintergund geschickt haben. Mit dem Befehl
$ screen -r barneywird die Session wieder mit dem Terminal verbunden.
4. Session Management
Mit den unter 3. erworbenen Mitteln wollen wir nun ein Session-Management aufbauen. Dazu erstellen wir drei Skripts. Die Beispiel-Skripts sind ksh-Skripts, sie sind aber kompatibel zur bash gehalten, tauschen Sie lediglich #!/bin/ksh gegen #!/bin/bash aus.
a. bin/screenwrapper
#!/bin/ksh
SESSION_ARGS="$@"
SESSION_NAME="$(echo $@ | awk '{print $NF}')"
SESSION_TERM=${TERM:-xterm}
if [ -z "$SESSION_ARGS" ]
then
$SESSION_CMD
else
case $SESSION_NAME in
-*)
$SESSION_CMD $SESSION_ARGS
;;
?*)
exec $screen -T $SESSION_TERM -h 10000 -S $SESSION_NAME $SESSION_CMD $SESSION_ARGS
;;
esac
fi
Dieses Skript baut eine Screen Session auf und übergibt das Kommando an die Session, der Name der Session ergibt sich aus dem Argument, also wenn wir
$ screenwrapper ssh homer
eingeben, sehen wir:
$ screen -list There is a screen on: 159936.homer (Attached) 1 Socket in /tmp/uscreens/S-armin
Für "screenwrapper ssh" setzen wir einen Alias in der Initialisierungsdatei für die Shell (z.B. .login für Bourne-Shell und ksh oder .bash_login für die Bash):
alias s='~/bin/screenwrapper ssh'
so dass wir einfach
$ s homer
eingeben können.
b. bin/lsscreens
Als nächstes brauchen wir ein Skript, das die Ausgabe aller laufenden Sitzungen anzeigt. Dies nennen wir z.B. lsscreens:
#!/bin/ksh
screen=$HOME/bin/screen
screens="$($screen -ls | grep tach | sed -e 's/[ ]/#/g')"
if [ -n "$screens" ]
then
printf "\n PID HOST STARTED@ ( STATE )\n"
for screen in $screens
do
pid=$(echo $screen | cut -d . -f1 | cut -d\# -f2)
stm=$(ps uax | egrep -w "$USER[ ]*$pid" | awk '{print $9}')
hst=$(echo $screen | cut -d . -f2 | cut -d\# -f1)
sta=$(echo $screen | cut -d\# -f3)
printf "%8d %-16s %-10s %s\n" $pid $hst $stm $(echo $sta | sed -e "s/\(Detached\)/^[[32m\1^[[0m/")
done
echo
else
printf "\n No screens in use.\n\n"
fi
Die Ausgabe gibt uns einen schnellen Überblick über alle ssh-Sessions, wann sie gestartet wurden und ob sie aktuell in einem Fenster laufen oder vom Terminal abgekoppelt wurden:
$ lsscreens PID HOST STARTED@ ( STATE ) 1110162 akira 10:01:46 (Detached) 671902 homer 10:02:01 (Attached) 1052876 barney 11:27:48 (Attached) 970912 bart 12:53:50 (Detached) 1048698 lisa 13:27:36 (Detached) 188568 bart 12:53:50 (Detached)
c. bin/attach
Screens, die sich im Status Detached befinden, können dann mit dem folgenden Skript, das im Wesentlichen screen -r ausführt, wieder mit einem Terminal verbunden werden:
#!/bin/ksh
screen="$HOME/bin/screen" SCREENARGS='-r' ARGS="" while (($#>0)) do case $1 in -f) SCREENARGS='-r -D' shift ;; *) HOSTNAME=$1 ARGS=$1 shift#must exit here
;; esac done $screen $SCREENARGS $ARGS
So verbinden Sie sich mit
$ attach akira
wieder mit der laufenden Verbindung zu akira. Haben Sie mehrer Sitzungen zum selben Rechner laufen, die sich im Status Detached befinden, würden Sie allerdings folgende Fehlermeldung bekommen:
$ attach bart There are several suitable screens on: 970912.bart (Detached) 188568.bart (Detached) Type "screen [-d] -r [pid.]tty.host" to resume one of them.
In diesem Fall müssen Sie den PID mit übergeben:
$ attach 188568.bart
Eine Verbindung, die in irgendeinem Terminal läuft, sich also im Status Attached befindet, lässt sich zunächst einmal nicht auf ein anderes Terminal bringen, weil sich mit attach bzw. screen -r nur solche Sitzungen an ein Terminal binden lassen, die nicht bereits anderswo verbunden sind. Doch unser Skript hat eine force-Option, die dies dennoch möglich macht:
$ attach -f barney
Nun wird die Session vom anderen Terminal getrennt und zu Ihrem aktuellen Terminal verbunden.