Expect Scripting
Im Alltag eines Shell-Benutzers ist man oft mit interaktiven Shell-Programmen konfrontiert. Will man diese automatisieren, kann man standardmäßig interaktive Eingaben per Kommandozeilenoption übergeben. Im Falle von
ssh
kann man die Passwortabfrage umgehen, indem man
passphraseless authentication
nutzt. Doch im Falle von
passwd
z.B. muss man sich anders weiterhelfen. Hier kommt
Expect
ins Spiel.
Expect
ist eine Skriptsprache zum Automatisieren interaktiver Shell-Programme. Es gibt Implementierung für diverse Programmiersprachen, z.B.
Tcl
,
PERL
,
Python
oder
Java
.
Beispiel: passwd
Anmerkung: Dieses Beispiel ist als Helloworldbeispiel zu verstehen. Es gibt sichere Möglichkeiten, passwd zu automatisieren. Z.B. mit chpasswd
Im Folgenden soll
passwd
"automatisiert" werden. Dazu erstellen wir ein Expect-Skript
autopasswd
mit der Befehlssyntax:
:~/# autopasswd username password
Eine einfache Version ohne Fehlerfallbehandlung könnte so aussehen:
1 #!/bin/expect
2 # wrapper to make passwd(1) be non-interactive
3 # username is passed as 1st arg, passwd as 2nd
4
5 set password [lindex $argv 1]
6 spawn passwd [lindex $argv 0]
7 expect "assword: $"
8 send -- "$password\r"
9 expect "assword: $"
10 send -- "$password\r"
11 expect eof
Zeile 5 definiert und initialisiert die Variable
password
mit dem übergebenen Passwort.
Zeile 6 ruft nun das interaktive
passwd
auf mit dem übergebenen Username, sodass Expect Kontrolle über Ein- und Ausgabe hat.
Zeile 7-10 warten jeweils auf einen bestimmten String und reagieren dann mit der Eingabe des Passworts auf
STDIN
(Standardeingabe).
Zeile 11 ist optional, beendet das Skript aber explizit und sauber.
Der Beispielcode ist wirklich nur eine sehr einfache Variante. Prinzipiell lassen sich auch komplexere Interaktionspfade mit
if
,
switch
und Schleifenstatements implementieren. Auch die Fehlerabhandlung sollte man nicht vergessen.
Anmerkung/Bug
Unter Debian (Das einzige System, auf dem ich getestet habe
) gibt es eine Besonderheit bzw. einen Bug (imo Ansichtssache).
passwd
erwartet nach der Ausgabe von
Enter new UNIX password:
nicht unmittelbar eine Eingabe, sondern erst ein paar Millisekunden verzögert. Dies macht für den Menschen keinen Unterschied, für eine Expect-Skript aber schon. Daher folgende Abänderung in Zeilen 8 und 11:
1 #!/bin/expect
2 # wrapper to make passwd(1) be non-interactive
3 # username is passed as 1st arg, passwd as 2nd
4
5 set password [lindex $argv 1]
6 spawn passwd [lindex $argv 0]
7 expect "assword: $"
8 sleep .1
9 send -- "$password\r"
10 expect "assword: $"
11 sleep .1
12 send -- "$password\r"
13 expect eof
autoexpect
Ohne dieses Features zu dokumentieren, möchte ich auf dessen Existenz hinweisen. Mit
autoexpect
lassen sich Interaktionen mit einem Shell-Programm aufzeichnen. So generierte Expect-Skripte können viel Arbeit ersparen.
Links/Installation
- Im Debian das Paket
expect
(enthält kein autoexpect
) oder expect-tcl8.3
(enthält autoexpect
) installieren.
- Projekthomepage: http://expect.nist.gov/
--
DennisKlein - 22 Jan 2009