I am using the following Expect script for remote SSH login to a Raspberry Pi and am executing the commands:
#!/usr/bin/expect
set timeout 60
spawn ssh [lindex $argv 1]@[lindex $argv 0]
expect "yes/no" {
send "yes\r"
expect "*?assword" { send "[lindex $argv 2]\r" }
} "*?assword" { send "[lindex $argv 2]\r" }
expect "pi@raspberrypi ~ $ " {
send "ls -la\r"
}
interact
The problem is that this script is able to log in into the Raspberry Pi, but when it comes to the line for executing the "ls -la" command, nothing happens. How can I fix this script? Where am I making the mistake?
OK, if I put the
exp_internal 1
line in my script, I get the following output in the where matching fails:
expect: does ": \r\nLinux raspberrypi 3.10.24+ #614 PREEMPT Thu Dec 19 20:38:42 GMT 2013 armv6l\r\n\r\nThe programs included with the Debian GNU/Linux system are free software;\r\nthe exact distribution terms for each program are described in the\r\nindividual files in /usr/share/doc/*/copyright.\r\n\r\nDebian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent\r\npermitted by applicable law.\r\nLast login: Mon Mar 3 19:00:11 2014 from 192.168.1.200\r\r\n\u001b]0;pi@raspberrypi: ~\u0007\u001b[01;32mpi@raspberrypi\u001b[00m \u001b[01;34m~ $\u001b[00m " (spawn_id exp6) match glob pattern "*pi@raspberrypi ~ $*"? no
Shouldn't this matching be true?
You should be using exp_continue to reenter your Expect loop after the password and authenticity checks are done. Try the below:
#!/usr/bin/expect
set prompt "pi@raspberrypi ~ $ "
spawn ssh [lindex $argv 1]@[lindex $argv 0]
set timeout 5
expect {
timeout {
puts "Connection timed out"
exit 1
}
"yes/no" {
send "yes\r"
exp_continue
}
"assword:" {
send -- "[lindex $argv 2]\r"
exp_continue
}
"$prompt" {
send "ls -la\r"
}
}
This is an extract taken from Exploring Expect regarding exp_continue by Don Libes:
When executed as an Expect action, the command exp_continue causes control to be continued inside the current Expect command. Expect continues trying to match the pattern, but from where it left off after the previous match. Expect effectively repeats its search as if it had been invoked again.
You might have a look at this... it takes a list of commands, contained in a file, and executes them on the remote host by interactively logging in and executing them one-at-a-time on the remote machine. You can turn on logging if you want to capture output, and you'll need to tweak it to handle your computer (or other device's) prompts:
#!/usr/bin/expect
#
# Read a list of commands and execute them on remote host
#
# WA2IAC 3/9/2015
#
spawn ssh -l username target_host
expect "ord\\: "
send "your_password\r"
set handle [ open commandfile.txt r ]
while { ! [eof $handle] } {
gets $handle buf
expect "\\$"
send "$buf\r"
}
interact
You can flesh this out by setting a timeout and handling things that can go wrong (see snippet above). Remove the "interact" statement to have the script exit when done (you could use a shell loop to execute this for a number of hosts/devices).
I've used this to send commands routers to update static routes, but it has many other uses. I got it from here: http://wa2iac.com/wiki/index.php?title=Expect_remote_commands
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With