How to return from shell 'read' command passed in expect script?
I have a shell script that calls an expect script I wrote to ssh login to another host and get user input regarding that host's network configuration. I pass four arguments to the expect script: the remote host ip address, the username, the password, and the list of commands to run. My expect script is below:
#!/usr/bin/expect # Usage: expectssh <host> <ssh user> <ssh password> <script> set timeout 60 set prompt "(%|#|\\$) $" set commands [lindex $argv 3]; spawn ssh [lindex $argv 1]@[lindex $argv 0] expect { "*assword:" { send -- "[lindex $argv 2]\r" expect -re "$prompt" send -- "$commands\r" } "you sure you want to continue connecting" { send -- "yes\r" expect "*assword:" send -- "[lindex $argv 2]\r" expect -re "$prompt" send -- "$commands\r" } timeout { exit } expect -re $prompt send -- "exit\r" } The script runs well, except that if I send a command such as 'read' that requires user input, the script does not continue or exit after the user presses enter. It just hangs. The commands I pass to the expect script and it's call are as follows: SCRIPT='hostname > response.txt;netstat -rn;read net_card?"What is the network interface card number? " >> response.txt; read net_mask?"What is the subnet mask? " >> response.txt' /usr/bin/expect ./expectssh.exp $hostip $usr $pswd "$SCRIPT" Any suggestions on how I can pass a command to my expect script that requires user input without it hanging? On a side note because I know it will come up - I am not allowed to do key-based automatic SSH login. I have to prompt for a username and password, which is done from my main shell script. Thanks for any suggestions and help you can provide! |
seems like setting up ssh with keys is far simpler (and secure) than to kludge something together to bypass the password prompt.
|
I was able to fix my problem. What was missing was an 'interact' command following the read statement so that it would wait for user input (implemented through an if statement). I also moved the commands to be run into a separate -re $prompt block within the expect command and just called exp_continue at the end of the "*assword:" and "you sure you want to continue connecting" conditions. The updated code is below if anyone is interested:
expect { -re "(.*)assword:" { send -s "[lindex $argv 2]\r" exp_continue } "denied, please try again" { send_user "Invalid password or account.\n" exit 5 } "incorrect" { send_user "Invalid password or account.\n" exit 5 } "you sure you want to continue connecting" { send -s "yes\r" exp_continue } -re $prompt { foreach cmd $commands { send -- "$cmd\r" if {[string first "read" "$cmd"] != -1} { interact "\r" return send -- "\r" } } } timeout { send_user "Connection to host [lindex $argv 0] timed out." exit 10 } eof { send_user "Connection to host failed." exit } } |
All times are GMT -5. The time now is 04:27 PM. |