Tải bản đầy đủ (.pdf) (8 trang)

Automating User Input with expect

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (76.18 KB, 8 trang )

107
■ ■ ■
CHAPTER 17
Automating User Input with
expect
T
he expect utility’s name suggests precisely what it does: “expect” some output from
an interactive program, and send the program some input in response. expect has much
more functionality than I cover in this chapter, but this chapter provides a good example
of how it can be used. To find more complete information, you can consult the expect
manual page.
You may find that when you try to automate a task, the utilities or tools you are using
don’t lend themselves well to scripting. In the past, use of the format or fdisk command
(along with many others) was difficult to automate. Today we have versions of these
utilities, such as sfdisk, that are much easier to use within a script. A more modern use
of expect might include logging into specialized hardware to gather information or to
customize settings, as is required when administering network routers, switches, and
firewalls.
This chapter presents a pair of scripts for automating the control of a serial terminal
server. This is a type of network-accessible hardware that looks very much like a network
hub or a switch with multiple RJ45 ports. Each physical port can be connected to serial
devices, such as serial consoles. Once consoles are attached to the terminal server, you
can telnet to a specific network port on the terminal server and establish a connection
with the attached console.
The first example in this chapter is a shell script that processes user-provided
command-line switches that specify what commands to send to the terminal server.
The second script, which is called by the first, is an expect script that performs all the
manual labor. expect is an extension of the Tcl scripting language. expect was designed
to communicate with an interactive program, and it works well with ssh, telnet, ftp,
and other interactive utilities.
108


CHAPTER 17

AUTOMATING USER INPUT WITH EXPECT
A Shell Script to Customize Parameters for an
expect Script
The first script obtains the user input necessary to connect to the desired terminal
server(s) and perform the intended tasks. It displays usage instructions and allows the
user to specify a specific terminal server or to provide a file containing node names if there
are multiple terminal servers with which the user wants to communicate in the same way
and at the same time. First we need to define a few variables:
#!/bin/sh
NODE=""
CMDS=""
NODEFILE=""
AUTO=""
USAGE="There is a problem with the command, type $0 -h for syntax"
The variables are initialized to null strings, except for the USAGE variable, which
contains a message that is displayed whenever the script finds a problem with the
command-line call the user provided.
The script gets the information it needs from the user on the command line, so we
check that switches have been passed.
if [ $# -eq 0 ]
then
echo $USAGE
exit 1
fi
If no switches are passed to the script, the script displays the usage statement and quits
with a nonzero return code (here, 1).
The next section is where the command-line switches are handled.
while getopts idhlc:f:n: opt

do
case $opt in
i) CMDS="$CMDS \"sho ip\""
;;
The code uses the getopts construct, which is explained in greater detail in Chapter 5.
The -i switch indicates that the terminal server’s IP settings should be displayed. It causes
the command sho ip to be appended to the CMDS variable, which holds the commands
that will be sent to the terminal server.
Next we account for customized commands.
c) CUSTOM_CMD=$OPTARG
CMDS="$CMDS \"$CUSTOM_CMD\""
;;
CHAPTER 17

AUTOMATING USER INPUT WITH EXPECT
109
The -c switch is for user-provided terminal-server commands that aren’t hard-coded
in the script. The user can provide as many such commands as desired when invoking the
shell script, as long as a -c option precedes each command and the command itself is
double-quoted; most commands interpreted by the terminal server contain multiple
words that are space-delimited and so need to be tied together with quotes when the shell
script is called.
The OPTARG variable used in handling the -c switch is part of the getopts construct.
Note that this switch is followed by a colon in the getopts specification. When a colon
follows a switch in the getopts command, getopts will expect some type of argument to
follow that switch whenever it is used. OPTARG is the variable that receives the additional
argument to the switch. For example, if you had a script that takes a command-line
parameter to specify an optional input file, the invocation might look something like this:
sample_script -f input_file. The corresponding getopts line would look like this: while
getopts f:<other switches> opt, and OPTARG would be set to the string "input_file".

The -h switch causes the script to display its usage information.
h) cat << EOT
Usage:
$0 [-idhl] [-c "custom command"] [-f node_file] [-n node]
where:
-i Sends the "sho ip" command to the Xyplex terminal server
-d Logs in and drops you to the command prompt
-h Displays this information
-l Logs out ports 1-15
-c Takes a custom command and sends it to the terminal server.
Double quotes are required. You can have as many of these as you like.
-f Defines a file with a list of terminal servers to apply the commands to.
-n Defines a specific node to apply the command to.
EOT
exit 0
;;
Note that the cat command is used here to format the output, instead of multiple echo
commands. Chapter 28 contains more discussion of free-format output using cat.
The -d switch in the following code indicates that the terminal-server session is not
automated, and that the user simply wants to be left at a prompt after logging in:
d) AUTO="no"
;;
The presence of this switch causes the AUTO variable to be set to no. The expect script
examines this variable, and if it is set to no, the expect script leaves the user at the com-
mand prompt of the terminal server’s shell after logging in, and performs any commands
specified via the other options before logging out automatically. (See the following sec-
tion, “An expect Script to Automate telnet.”) If the AUTO variable is left undefined, the
110
CHAPTER 17


AUTOMATING USER INPUT WITH EXPECT
script will perform any specified tasks in an automated fashion without any user
interaction.
The -l switch adds a command to tell the terminal server to log out all of its serial ports.
l) CMDS="$CMDS \"logout por 1-15\""
;;
On occasion, a terminal server will have a hung and unresponsive serial port. A
command to log it out resets the port and it becomes usable again. The preceding CMDS
variable assignment is an example of a command that performs an action on managed
hardware. This command is specific to the hardware involved.
The -f switch specifies a file containing a node list (that is, a list of terminal servers).
f) NODEFILE=$OPTARG
;;
The script loops through the list of terminal servers and performs the specified com-
mand(s) against each one.
The -n switch indicates that a specific terminal-server node is the target, rather than
those in a list of nodes, as specified using the previous switch.
n) NODE=$OPTARG
;;
The following are two alternatives for robustness:
?) echo $USAGE
exit 1
;;
*) echo $USAGE
exit 1
;;
esac
done
If anything besides the anticipated options were provided in the invocation of the
script, the script should echo the contents of the USAGE variable to the screen, and exit.

Finally, after processing the switches and building the command list, the script calls
the expect script to contact the terminal server. If a NODEFILE was specified using the -f
switch, it validates the file and then iterates through it, calling the expect script once for
each terminal server with the parameters the user supplied. If a NODEFILE was not speci-
fied by the user via the -f switch, the script validates that an individual terminal server
was specified with the -n switch and that the NODE variable is not null. If the NODE variable
is null, the expect script is called with the appropriate parameters; otherwise it displays
the usage string.
if [ "$NODEFILE" != "" ]
then
CHAPTER 17

AUTOMATING USER INPUT WITH EXPECT
111
if [ -s $NODEFILE ]
then
for node in `cat $NODEFILE | grep -v '^#'`
do
eval ./xyp_connect $NODE $AUTO $LOGNAME $CMDS
done
else
echo There is a problem with $NODEFILE
fi
else
if [ "$NODE" != "" ]
then
eval ./xyp_connect $NODE $AUTO $LOGNAME $CMDS
else
echo $USAGE
fi

fi
The eval command is used here to evaluate the variables on that line of code once
before the code is executed. This is because the CMDS variable may contain terminal-
server commands that are, as a result of the processing of the switches, surrounded by
backslash-escaped double quotes; these escaped characters must be replaced with
unmodified quotes or else the multiple commands will be read incorrectly as one long
command. This is also where the call to the xyp_connect expect script that performs the
interactive functions takes place.
An expect Script to Automate telnet
The xyp_connect script, an expect script, performs the communication with the interac-
tive program used to connect to the terminal server, in this case telnet. The script starts
out by initializing some variables to hold the parameters that the shell script passed to it.
These parameters are accessed by their positions in the argument vector, argv[], of the
expect script’s process. The -f switch in the first line of the following code is used so the
script will accept additional command-line options.
#!/usr/bin/expect -f
set TERMSERV [lindex $argv 0]
set AUTO [lindex $argv 1]
set USER [lindex $argv 2]
The first parameter is the terminal server to which the expect script will attach. The
second parameter defines if this will be an automated session in which the expect script
performs the work, or an interactive one in which the script simply logs you in and leaves
you at the terminal-server shell prompt. The third parameter is the user who is to be
logged in.

×