Search code examples
sshexpect

Expect script for remote SSH login and executing commands


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?


Solution

  • 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.