expect script to ssh returns invalid command name

2019-06-19 02:03发布

问题:

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.

回答1:

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"}


回答2:

Thanks Glenn, it's working now. One more reason why it was not working was it requires to sleep between normal login and sudo login, otherwise "sudo su" were being sent before the $ prompt returned, for reference to others, here is the code,

#!/usr/bin/expect -f
#! /bin/bash

set timeout 60
log_user 1
set host *.*.*.*
set password ****** 
set user subhasish
set logfile output.txt
spawn ssh -p 10022 $user@$host
expect "*?assword:*"
send -- "$password\r"
#log_user 1
sleep 2
expect "$"
send -- "sudo su\r"
expect -gl {*password for subhasish:*}
send -- "$password\r"
expect "#"
send -- "service iptables status\r"
log_file /home/subhasish/output.log
expect "#"
log_file
send -- "exit\r";
send -- "exit\r";
exit 0


标签: expect