expect script to ssh returns invalid command name

Subhasish Chatterjee picture Subhasish Chatterjee · Apr 25, 2013 · Viewed 18.5k times · Source

I am trying to write an expect script which would ssh into a server, send sudo su, then check the iptables status and put the output in a log file on the server. Below is the script.

1 #!/usr/bin/expect
  2 exp_internal 1
  3 log_user 0
  4 set timeout 10
  5 set password  "******"
  6 
  7 spawn /usr/bin/ssh -l subhasish *.*.*.* -p 10022
  8 
  9 expect {
 10      -re "password: " {send "$password\r"}
 11      -re "$ "  {send "sudo su\r"}
 12      -re "[sudo] password for subhasish:" {send "$password\r"}
 13      -re "# "  {send "service iptables status\r"}
 14        }
 15 set output $expect_out(buffer)
 16 send "exit\r"
 17 puts "$output\r\n" >> output.log

But while run in debug mode, I am getting error like this;

expect -d testcase
expect version 5.44.1.15
argv[0] = expect  argv[1] = -d  argv[2] = testcase  
set argc 0
set argv0 "testcase"
set argv ""
executing commands from command file testcase
parent: waiting for sync byte
parent: telling child to go ahead
parent: now unsynchronized from child
spawn: returns {24105}
invalid command name "sudo"
    while executing
"sudo"
    invoked from within
"expect {
     -re "password: " {send "$password\r"}
     -re "$ "  {send "sudo su\r"}
     -re "[sudo] password for subhasish:" {send "$password\r"}
 ..."
    (file "testcase" line 9)

Not sure where I am going wrong. It says invalid command name "sudo", I guess this is because expect doesn;t understand these command. How to go around it. Please help. Thanks.

Answer

glenn jackman picture glenn jackman · Apr 26, 2013

The problem is in this line

-re "[sudo] password for subhasish:" {send "$password\r"}

In Tcl (and hence in expect) the square brackets are the syntax for command substitution (like backticks in the shell). So you either need to escape the brackets or use different quotes that prevent various expansions:

-re {[sudo] password for subhasish:} {send "$password\r"}

That brings up a different issue: are you expecting to see these exact characters? Because you're instructing expect to treat that as a regular expression, and square brackets in a regular expression means a character class, so it will match a single character, either a 's', 'u', 'd' or 'o'. So what you probably need is this:

-re {\[sudo\] password for subhasish:} {send "$password\r"}

or

-ex {[sudo] password for subhasish:} {send "$password\r"}