Programme fernsteuern mit expect

Inhalt

Zweckbestimmung

In den meisten UNIX-Systemen gibt es die Möglichkeit, lokale oder entfernte Terminalemulationen an Pseudo-Terminalschnittstellen zu betreiben. Das betrifft z.B. jedes xterm. Diese Pseudo-Terminalschnittstellen, unter Linux als /dev/pty* bezeichnet, erlauben es, anderen Programmen ein tatsächliches Terminal vorzuspielen.

Don Libes kam auf die Idee, eine frei programmierbare Schnittstelle zu beliebigen textorientierten Programmen über solche Pseudo-Terminals zu realisieren. Er schrieb dazu eine C-Bibliothek und integrierte einen Tcl-Interpreter. Da Tcl direkt dazu gedacht ist, in andere Programme eingebettet zu werden, eignete es sich für diesen Zweck besonders gut. Er benannte seine Tcl-Erweiterung nach dem besonders häufig benutzten und mächtigen Befehl expect, der es erlaubt, auf bestimmte Ausgaben anderer Programme zu warten und darauf zu reagieren.

Expect ist, da teilweise durch amerikanische Steuergelder finanziert, Public Domain Software, daß heißt, jeder kann es frei für jeden Zweck benutzen und modifizieren. Man bekommt die neueste Version jeweils von der expect-Homepage oder ftp://expect.nist.gov/mel/div826/subject/expect/expect.tar.gz. Unter http://expect.nist.gov/FAQ.html findet man auch eine FAQ zu expect.

Was kann man damit nun anfangen? Da gibt es sicher hunderte Möglichkeit. Nur so als Anregung:

expect läßt sich ab Tcl-7.4 bzw. Tk-4.0 einsetzen. Es läuft auch mit Tcl-8.0 bzw. Tk-8.0. Bis dato ist es nur auf UNIX-Systemen verfügbar, es gibt keine Variante für Windows oder Mac.

Die 4 Hauptbefehle in expect

Wie Don Libes im README schreibt, kann man alles über expect aus der manpage erfahren, sollte dort aber mit dem Text über die Befehle spawn, expect, send und interact, genau in dieser Reihenfolge, beginnen. Tatsächlich machen diese Befehle den Kern des Pakets expect aus und reichen (zusammen mit etwas grundlegendem Tcl) aus, nützliche Scripte zu schreiben. Gehen wir also in besagter Reihenfolge vor:

spawn

Dieser Befehl dient dazu, einen anderen Prozeß so zu erzeugen, daß er mit einem Pseudo-Terminal verbunden ist. Dieses Pseudo-Terminal wird wiederum von unserem expect-Script gesteuert. Nach dem Aufruf von spawn ist eine eindeutige Referenz zu diesem Prozeß in der Variable spawn_id zu finden. Diese Referenz kann später benutzt werden, genau diesen Prozeß auszuwählen. Damit lassen sich auch von einem Script mehrere Prozesse fernsteuern.

expect

Der Befehl expect erwartet eine bestimmte Ausgabe eines Prozesses. Dabei wird normalerweise ein Timeout von 10 Sekunden benutzt, was sich aber durch eine Zuweisung an die Variable timeout auch anders regeln läßt. Der Vergleich der Ausgabe mit dem Suchmuster kann dabei über einfaches "globbing", so wie in der Shell, über einen exakten Stringvergleich oder über reguläre Ausdrücke erfolgen. Ein Befehl expect kann mehrere Paare aus Suchmuster und Aktion erhalten. Ein Beispiel, daß aus einem Modem-Chat stammen könnte, soll das etwas verdeutlichen:
set timeout 70
expect {
  "BUSY" retry
  "NO *" abort
  "CONNECT" go_on
}

send

Dieser Befehl ermöglich das Senden von Daten an den ferngesteuerten Prozeß, so, als würden diese vom Benutzer stammen. Damit haben wir bereits alles zusammen, um unser Passwort ohne lästige Nachfrage ändern zu können:
#!/usr/local/bin/expect
set oldpass [lindex $argv 0]
set newpass [lindex $argv 1]
spawn passwd
expect "Old password:" {send "$oldpass\r"}
expect "New password:" {send "$newpass\r"}
expect "Re-enter new password:" {send "$newpass\r"}
expect {
  "Password changed." {puts stdout "\nPaßwort erfolgreich geändert"}
  default {puts stdout "\nHat nicht funktioniert!"}
}
Man beachte, daß der Code für die Return-Taste (\r) mit angegeben werden muß, sonst betrachtet der Prozeß die Eingabe nicht als abgeschlossen. Außerdem kann man im Moment noch den Ablauf des Scripts am Bildschirm mitverfolgen. Will man das unterdrücken, so fügt man am Anfang den Befehl log_user 0 ein. In expectk, der Tk-Version von expect, muß man übrigens send durch exp_send ersetzen, da send schon ein Tk-Befehl ist (mit dem sich Befehle in einem anderen Tk-Interpreter auf der gleichen Maschine ausführen lassen).

interact

Bei diesem Befehl wird die Steuerung zurück an den Benutzer übergeben. Das kann man z.B. dazu benutzen, den Benutzer nach dem Login automatisch an eine bestimmte Stelle einer umfangreicheren Anwendung zu navigieren und ihn dann dort weitermachen zu lassen.

Auch bei interact kann man, wie bei expect Paare von Suchmustern und Aktionen angeben. Die Überwachung auf das Suchmuster erfolgt dann im Hintergrund. Damit kann man auch recht einfach Tiphilfen bauen, die Abkürzungen wie "mfg" nach "Mit freundlichen Grüßen" übersetzen.

#!/usr/local/bin/expect
if {[llength $argv]==0} {
  set file foo
} else {
  set file [lindex $argv 0]
}
spawn vi $file
interact {
  mfg {send "Mit freundlichen Grüßen"}
  sgdh {send "Sehr geehrte Damen und Herren,"}
}

Beispielanwendung

Tragen wir also das schon gesagte und einige Tk-Befehle zusammen, um eine grafische Oberfläche für passwd zu schreiben:

Hier ist das fertige Script

Andere Tcl-Erweiterungen

Expect ist nur eine von einer ganzen Menge verschiedener Tcl-Erweiterungen. Diese Vielfalt ist ein Zeichen dafuer, dass es wirklich recht einfach ist, den Tcl-Interpreter in eigene Anwendungen einzubauen. Es ist mitlerweile nahezu unmöglich, alle Erweiterungen zusammenzutragen und zu beschreiben. Ein guter Ausgangspunkt für die Suche sind folgende URL's:

Hier folgt eine Zusammenstellung der Tcl/Tk-Erweiterungen, über die ich schonmal was gelesen oder die ich selbst ausprobiert habe:

TclX erweiterte Funktionen in der UNIX-Umgebung, z.B. Signalbehandlung
TiX Eine Menge neuer Widgets für Tk, z.B. Combobox
BLT Funktionen zum Zeichnen von Graphen
TkTable Tabellen-Widget
TkStep Anpassung des Tk-Aussehens an NeXT- bzw. Afterstep. Enthält auch Unterstützung für Drag and Drop und XPM- sowie TIFF-Images
adabastcl Zugriff auf die Datenbank Adabas-D der Software AG
Pgtcl Zugriff auf die Datenbank PostgreSQL bzw. Postgres-95
msqltcl Zugriff auf mSQL. Es gibt auch einen Patch dazu, der den Zugriff auf mysql erlaubt.
tclodbc Erlaubt den Zugriff auf viele Datenbanken über ODBC. Leider nur unter Windows

und hier noch einige größere Anwendungen, die mit Tcl/Tk, teilweise unter Benutzung der Erweiterungen, geschrieben wurden

TkDesk Leistungsfähiger Filemanager für UNIX
tclhttpd Ein Webserver als Tcl-Script realisiert. Wird zum Beispiel vom Sunscript-Server verwendet. Vorteil: statt CGI einfach Scripte in den Interpreter "sourcen", dadurch muß nicht jedesmal ein Prozeß gestartet werden. Vergleichbar Java-Servlets
Webtk Ein HTML-Editor
Tk-Cicero Eine Textverarbeitung. Habe ich leider bisher nicht übersetzen können.