Using expect for System Administration
Noel Davis
Shell scripting is a very common tool used for a system
administrator. Automating every task we can is one of the things
that sets us apart as Unix System Admins. It allows us the time to
work on the important things without staying bogged down in the minutia
of running a system. In this article I will introduce you the very
powerful though unusual scripting language Expect.
The FAQ describes expect as:
Expect is a tool primarily for automating interactive applications
such as telnet, FTP, passwd, fsck, rlogin, tip, etc. Expect really
makes this stuff trivial. Expect is also useful for testing these
same applications. Expect is described in many books, articles,
papers, and FAQs. There is an entire book on it available from
O'Reilly.
Expect is free and in the public domain. Download instructions can
be found in the Expect homepage.
The part you should pay attention to is "Expect really makes this
stuff trivial." Expect is an easy way to automate those tasks you end
up doing again and again because they span different machines or
because it requires more interaction than you can get easily from a
bash/c/korn shell script. It was written by John Ousterhout and
compiles on most if not all Unix machines.
Expect is based on tcl, but is very usable without knowing hardly
anything about tcl. Tool Command Language (TCL) was written as a
standard scripting language to be included with utilities so people
would not have to hack together their own languages. As for myself I
have always been amazed that tcl could come out of the mind of a c
programmer and have been glad that I could use expect without becoming
a tcl expert.
There is an excellent book on programming in expect from O'Reilly
"Exploring Expect". It has some sort of monkey like creature on the
cover and was written by Don Libes. If you want to get into anything
complicated I would highly recommend it. Otherwise you should be able
to figure expect out by looking at the examples that come with the
source code.
For example the following program runs rlogin to the named machine and
then sets your DISPLAY to whatever it was on the source machine.
#!/depot/path/expect --
# xrlogin - rlogin but with current DISPLAY
#
# You can extend this idea to save any arbitrary information across rlogin
# Don Libes - Oct 17, 1991.
if {[llength $argv] != 1} {
puts "usage: xrlogin remotehost"
exit
}
set prompt "(%|#|\\$) $" ;# default prompt
catch {set prompt $env(EXPECT_PROMPT)}
set timeout -1
eval spawn rlogin $argv
expect eof exit -re $prompt
if [string match "unix:0.0" $env(DISPLAY)] {
set env(DISPLAY) "[exec hostname].[exec domainname]:0.0\r"
}
send "setenv DISPLAY $env(DISPLAY)\r"
interact
This is not a very complex program and can be easily modified to do
many other things. It could set your current working directory to the
same as the source machine. (One of the other examples.) It could
execute a series of tasks once you have connected. It can also
execute a task and then act differently based on what happens.
One of the tasks I have ended up doing on a regular basis has been to
generate and then distribute a password and shadow file to multiple
machines. There are multiple steps involved on multiple machines and
it took about a half hour of my time before I automated it with
expect. The automated version of it takes about 15 seconds of my
time. I am going to pull a couple of examples out of this script to
illustrate some features of expect.
At a point in the script I am
copying the passwd file to a backup copy and want to make sure that I
always have a backup and never overwrite a backup file by mistake.
send "cp -i passwd passwd.$date\n"
expect "overwrite" {interact "+" return}
send "\n"
In this I send the cp command and if expect sees the string
"overwrite" it stops (thats what interact is) goes interactive and
lets me decide manually what to do. When I have finished I start the
script up again with the + key.
Also in this script I have to cp the new password and shadow files to
multiple machines. To do this I use scp which requires a passphrase.
Rather than enter the passphrase for each scp I am prompted for it
once and the script enters it for each scp.
send "scp Shadow-New root@hostname:/etc\n"
expect "Enter passphrase for RSA key" {send "$PASSPHRASE\n"}
expect "#"
The example scripts included with Expect include rftp - get
and entire directory using ftp at the touch of one key, passmass -
Change passwords on multiple machines and many more. If you would
like to learn more about expect I would recommend that you download it
and just take a look at the examples. There is more than enough there
to get you started.
I am not making any claims that the way that these problems that I
described were solved was the best way possible, but they were solved
for me and this allowed me to move on to the next problem. They were
also solved without making any changes to the system that would have
to be explained to other people or documented for them. The scripts I
described do nothing
that I could not do by typing but do it more accurately than I could do
the task and with much less effort.
The only claim I do make is that Expect has been a very useful tool in
my tool belt.
|