Expect Scripts


Gaming Laptop Series

How to send escape characters through Expect http://mini.net/tcl/3038
How to send escape characters through Expect http://mini.net/tcl/201
Expect Send Function Keys
Function Keys, Escape Sequences, in expect

Esc+9
send \0339

Esc+A
send \033A

F9
send ???

Up

Down
send — “^[\[B”
(Please note that the ^[ is the escape character, which is one character, and not two separate characters(not ^ and [). I’m not sure how to generate this inside of vi, so I just copy and paste it. You can do this to get it in your file: echo -e “\033” >> myfile.exp)

Left

Right

We have also found that some implementations, such as over a serial port, may require a moment of silence after sending an escape sequence. When we sent multiple escape sequences back to back in one situation (speaking to a BIOS over the serial port) that the BIOS would refuse the escape sequences.

You can determine this same info by doing the following:

run “od -c”
Press the key you are interested in followed by the return key followed by Ctrl+D.
You should then see the following output (we pressed the down arrow here):

[user@localhost user]$ od -c
^[[B
0000000 033   [   B  \n
0000004
[user@localhost user]$

So we want everything between the 0000000 and the \n, and you have to escape the left bracket for expect so it doesn’t think you are giving it a system command.
Here’s some ascii tables if you need more help: http://www.jimprice.com/jim-asc.shtml


SSH AutoLogin

I would like this to be a bit cleaner in expect, but I’m not an expert at writing expect scripts. Nevertheless, this script runs just as well. For more notes on SSH autologin (using an identity key) see sshkeys.html. If anyone would care to clean this up so there is less duplicated code, I would really appreciate it.

The one special character you see below is CTRL+D which usually translates to either logout or exit. You can get this character in the editor on a linux box by typing ctrl+v ctrl+d (in insert mode).

This program accepts command line arguments. The arguments are the commands you want run on the destination box. Right now I have the ipaddress fixed in this script. Later I would add something so I could pass the ip address of the destination box. Also you can pass several commands to run on the remote box by separating them with a semicolon. The semicolon and pipe commands will need to be escaped so your own shell doesn’t interpret and use the semicolon.

Here’s a sample calling with 3 commands and a pipe command to be run on the remote box:

./script.exp ls \; /sbin/ifconfig \| grep inet \; ls /

#!/usr/bin/expect -f
#
# This Expect script was generated by autoexpect on Tue Mar 18 15:38:55 2003
# Expect and autoexpect were both written by Don Libes, NIST.
#
# Note that autoexpect does not guarantee a working script.  It
# necessarily has to guess about certain things.  Two reasons a script
# might fail are:
#
# 1) timing - A surprising number of programs (rn, ksh, zsh, telnet,
# etc.) and devices discard or ignore keystrokes that arrive "too
# quickly" after prompts.  If you find your new script hanging up at
# one spot, try adding a short sleep just before the previous send.
# Setting "force_conservative" to 1 (see below) makes Expect do this
# automatically - pausing briefly before sending each character.  This
# pacifies every program I know of.  The -c flag makes the script do
# this in the first place.  The -C flag allows you to define a
# character to toggle this mode off and on.

set force_conservative 0  ;# set to 1 to force conservative mode even if
			  ;# script wasn't run conservatively originally
if {$force_conservative} {
	set send_slow {1 .1}
	proc send {ignore arg} {
		sleep .1
		exp_send -s -- $arg
	}
}

#
# 2) differing output - Some programs produce different output each time
# they run.  The "date" command is an obvious example.  Another is
# ftp, if it produces throughput statistics at the end of a file
# transfer.  If this causes a problem, delete these patterns or replace
# them with wildcards.  An alternative is to use the -p flag (for
# "prompt") which makes Expect only look for the last line of output
# (i.e., the prompt).  The -P flag allows you to define a character to
# toggle this mode off and on.
#
# Read the man page for more info.
#
# -Don

#set DO_TASK "wget ftp://172.16.0.4/pub/tests/testme.sh; sh ./testme.sh >stdout.log 2>stderr.log; (echo stderr; cat stderr.log; echo stdout; cat stdout.log) | mail -s testing riblack@mydomain.net; rm -f ./testme.sh\r"
if { "x$argv" == "x" } {
send_user "\nPlease specify command to run.\r\n"
exit 1 }
catch {set DO_TASK "$argv\r"}
regsub -all {\{} $DO_TASK {} DO_TASK
regsub -all {\}} $DO_TASK {} DO_TASK
if { "x$DO_TASK" == "x" } {
send_user "\nSorry, DO_TASK died.\r\n"
exit 1 }

set timeout -1
spawn $env(SHELL)
match_max 100000
expect "*\]\$ "
send -- "ssh root@172.32.0.243\r"
expect {

"The authenticity of host '172.32.0.243 (172.32.0.243)' can't be established.\r
RSA key fingerprint is *.\r
Are you sure you want to continue connecting (yes/no)? " {
send -- "yes\r"
expect "yes\r
Warning: Permanently added '172.32.0.243' (RSA) to the list of known hosts.\r\r"
expect {

"root@172.32.0.243's password: " {
send -- "password\r"
expect "Last login: *\r\r
*root\]# "
send "wget ftp://172.16.0.4/pub/tests/id_dsa.pub; mkdir -p ~/.ssh; cat id_dsa.pub >> ~/.ssh/authorized_keys2; rm -f id_dsa.pub\r"
expect "*root\]# "
send -- "$DO_TASK"
expect "*root\]# "
send -- ""
expect "logout\r
*Connection to 172.32.0.243 closed.\r\r
*\]\$ "
send -- ""
expect eof


} "Last login: *\r\r
*root\]# " {
send -- "$DO_TASK"
expect "*root\]# "
send -- ""
expect "logout\r
*Connection to 172.32.0.243 closed.\r\r
*\]\$ "
send -- ""
expect eof
}
}


} "root@172.32.0.243's password:" {
send -- "password\r"
expect "Last login: *\r\r
*root\]# "
send -- "$DO_TASK"
expect "*root\]# "
send -- ""
expect "logout\r
*Connection to 172.32.0.243 closed.\r\r
*\]\$ "
send -- ""
expect eof



} "Last login: *root\]# " {
send -- "$DO_TASK"
expect "*root\]# "
send -- ""
expect "logout\r
*Connection to 172.32.0.243 closed.\r\r
*\]\$ "
send -- ""
expect eof



} "Host key verification failed." {
send -- "cat ~/.ssh/known_hosts | grep -v 172.32.0.243 > ~/.ssh/known_hosts1; mv ~/.ssh/known_hosts1 ~/.ssh/known_hosts; ssh root@172.32.0.243\r"
exp_continue



}
}

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.