GästebuchIhr Eintrag in unser Gästebuch KontaktNehmen Sie Kontakt mit den Autoren auf ArchivAlle Unixwerk- Artikel seit 2003
14. Juni 2009

Session-Management mit »screen«

Inhalt

  1. Einleitung
  2. »screen« installieren
  3. Grundlegende Kommandos
  4. Session Management
  5. Tipps

 

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.

Update:
Der Server »aixpdslib.seas.ucla.edu« scheint seit einiger Zeit tot zu sein. Als Alternative lässt sich auch das Paket gnu.screen-3.9.8.0 von Bull ins Heimatverzeichnis entpacken:

$ cd
$ chmod +x gnu.screen-3.9.8.0.exe
$ ./gnu.screen-3.9.8.0.exe
  inflating: gnu.screen-3.9.8.0.bff  
  inflating: gnu.screen-3.9.8.0.bff.asc  
$ restore -xvqf gnu.screen-3.9.8.0.bff
$ mv usr/local/* .
$ rm -rf ./usr

Damit die von Bull kompilierte Version von screen aus dem Heimatverzeichnis heraus funktioniert, ist noch ein bisschen zusätzliche Handarbeit notwendig. Zunächst muss die Konfigurationsdatei aus dem Verzeichnis lib/screen-3.9/etc ins Heimatverzeichnis kopiert werden:

$ cp ~/lib/screen-3.9/etc/screenrc ~/.screenrc

Dann müssen ein paar Umgebungsvariablen so gesetzt werden, dass screen nicht versucht in geschützte Verzeichnisse zu schreiben - diese könnte man z.B. in sein lokales Profile eintragen:

export SCREENDIR=$HOME/tmp/screen

Update2:
Auch unter Solaris lässt sich screen im Heimatverzeichnis installieren. Das folgende Beispiel zeigt die Installation für Solaris 9 für Sparc.

Dazu habe ich mir von www.sunfreeware.com die Pakete screen-4.0.2-sol10-sparc-local.gz und ncurses-5.6-sol10-sparc-local.gz (die 10er-Pakete sind auch unter Solaris 9 lauffähig!) heruntergeladen und in meinem Heimatverzeichnis entpackt:

$ cd $HOME
$ mkdir .tmp
$ gunzip screen-4.0.2-sol10-sparc-local.gz
$ pkgtrans screen-4.0.2-sol10-sparc-local $PWD/.tmp

The following packages are available:
  1  SMCscreen     screen
                   (sparc) 4.0.2

Select package(s) you wish to process (or 'all' to process
all packages). (default: all) [?,??,q]: all
Transferring  package instance

$ gunzip ncurses-5.6-sol10-sparc-local.gz
$ pkgtrans ncurses-5.6-sol10-sparc-local  $PWD/.tmp

The following packages are available:
  1  SMCncurs     ncurses
                  (sparc) 5.6

Select package(s) you wish to process (or 'all' to process
all packages). (default: all) [?,??,q]: all
Transferring  package instance

$ cd $HOME/.tmp/SMCscreen/reloc
$ tar cpBf - ???* | ( cd $HOME && tar xpBf - )
$ cd $HOME/.tmp/SMCncurs/reloc
$ tar cpBf - ???* | ( cd $HOME && tar xpBf - )
$ rm -rf $HOME/.tmp/SMC*

Ein bisschen Nacharbeit ist noch erforderlich - für die Bibliotheken müssen ein paar Links gesetzt werden und das Verzeichnis für die Sockets muss angelegt werden:

$cd $HOME/lib
$ln -s libncurses.so.5.6 libncurses.so.5
$cd $HOME/bin
$ln -s screen-4.0.2 screen
$mkdir -p  $HOME/.tmp/screens
$chmod 0700 $HOME/.tmp/screens

Zu guter Letzt müssen einige Umgebungsvariablen gesetzt werden, damit screen seine Bibliotheken findet und nicht versucht in geschützte Verzeichnisse zu schreiben - diese könnte man z.B. in sein lokales Profile eintragen:

export LD_LIBRARY_PATH=$HOME/lib
export SCREENDIR=$HOME/.tmp/screens
export PATH=$PATH:$HOME/bin
export SYSSCREENRC=$HOME/etc
export TERMINFO=$HOME/share/terminfo

 

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 barney

wird 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_CMD="$1"
shift
SESSION_ARGS="$@"
SESSION_NAME="$(echo $@ | awk '{print $NF}')"
SESSION_TERM=${TERM:-xterm}
screen="$HOME/bin/screen"

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
Beachten Sie in diesem Skript, dass "^[" ein Zeichen, nämlich <ESC>, ist. Im vi erreichen Sie dies, indem Sie <Ctrl-V><ESC> eingeben. Beachten Sie ferner, dass in dem regulären Ausdruck "/[     ]/" einmal <SPACE> und einmal <TAB> stehen.

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.

 

5. Tipps

Wie wir gesehen haben, wird ein Screen mit ^AD in den Hintergrund geschickt. Diese Tastenkombination führt im Zusammenhang mit dem Emacs-Mode von bash, ksh, tcsh oder zsh zu Problemen: Mit ^A springt man hier zum Anfang der Kommandozeile - doch in einer Screen-Session leitet man mit ^A ein Screen-Kommando ein (z.B. eben Detach). Um hier Konflikten zu entgehen, empfiehlt es sich einen anderen Buchstaben zu definieren. Folgendes kann man z.B ans Ende seiner ~/.screenrc setzen:

escape ^gg

Damit würde nun ^G anstelle von ^A ein Screen-Kommando einläuten. Gibt es noch keine Datei .screenrc in Ihrem Heimatverzeichnis, kann dies auch der einzige Eintrag sein.