issue with expect exception handling in foreach loop - bash

I have a expect script that fires commands on remote devices, some of the devices can have credentials issues for which I need to skip is the password prompt repeats after entering the password.
#!/usr/bin/expect -f
set x [list 192.168.1.1 192.168.1.2]
foreach hosts $x {
# spawn ssh sy-nep-oss#$x
sleep 5
spawn ssh -o StrictHostKeyChecking=no sy-nep-oss#$hosts
sleep 5
**expect {"password: "
send -- "abcd\r"
expect "*>"
If the password is incorrect, need to skip this loop iteration and move on to the next item in the list
send -- "cd cfcard:/ \r"
sleep 2
expect "*>"
send -- "cd cfcard2:/ \r"
sleep 2
expect "*>"
sleep 2
send -- "dir log* \r"
expect "*>"
sleep 2
send "cd log \r"
expect {enter code here
"Error: Wrong path *" {
send "cd logfile \r"
}
"logfile*" {
send "cd log \r"
}
}
expect "*>"
sleep 2
send -- "dir log.log \r"
expect "*>"
sleep 2
send -- "system-view \r"
expect "Enter system view*"
sleep 2
send -- "sftp 212.72.10.182 \r"
expect "*username*"
sleep 2
send -- "test\r"
expect "*password:"
sleep 2
send -- "Y\r"
sleep 3
send -- "N \r"
sleep 4
expect "Please select public key type for user authentication*"
send -- "R \r"
sleep 2
expect "*password"
sleep 2
expect "sftp-client>"
sleep 2
send -- "put log.log $hosts.log \r "
sleep 2
expect "sftp-client>"
sleep 2
send -- "quit\r"
sleep 2
send -- "quit\r"
sleep 2
send -- "quit\r"
}
expect eof

Related

Hiding Output from Expect Commands

so I have the following code and cant figure out how to only display one send command. I only need the result from the df -h send command.
#!/usr/bin/env bash
echo "Updating Source..."
/usr/bin/expect << EXPECT
log_user 0;
spawn -noecho ssh -p 7742 user#location
expect "username:"
send "username\r"
expect "password:"
send "password\r"
send "shell\r"
send "df -h\r"
send "exit\r"
sleep .5
send "exit\r"
interact
EXPECT
Try the following:
#!/usr/bin/env bash
echo "Updating Source..."
/usr/bin/expect << EXPECT
log_user 0;
spawn -noecho ssh -p 7742 user#location
expect "username:"
send "username\r"
expect "password:"
send "password\r"
send "shell\r"
log_user 1;
send "df -h\r"
log_user 0;
send "exit\r"
sleep .5
send "exit\r"
interact
EXPECT

Expect conditionals don't seem to be working

Edit: Everything works perfectly without the conditional. Adding in the conditional breaks the script. I've tried conditionals in other simpler scripts and those have worked.
Edit2: Adding the full script as other instances of expect conditionals have worked
I'm trying to modify an autoexpect generated expect script that works when the build succeeds but doesn't handle the build failing.
After significant research, I can't figure out why my expect conditional isn't working
#!/usr/bin/expect -f
set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
set timeout -1
spawn $env(SHELL)
match_max 100000
expect "~\$ "
send -- "sudo su\r"
expect "/home/ubuntu# "
send -- "cd ../../opt/application/"
send -- "\r"
expect "/opt/application# "
send -- "./buildwar.sh \r"
expect {
"BUILD SUCCESSFUL\r" {
send -- "su appuser\r"
expect "/opt/application\$ "
send -- "../../home/ubuntu/shutdown.sh \r"
expect "\"outcome\" => \"success\"}"
send -- "exit\r"
expect "/opt/application# "
send -- "./deploywar.sh \r"
expect "BUILD SUCCESSFUL"
send -- "su appuser\r"
expect "/opt/application\$ "
send -- "../../home/ubuntu/startup.sh \r"
expect "Deployed \"application.war\""
send -- "exit\r"
send -- "exit\r"
send -- "exit\r"
exit 0
}
"BUILD FAILED\r" {
exit 1
}
}
You may need to run with expect debugging on (expect -d). You don't actually show what data you are expecting.
It works for me:
$ expect -c '
log_user 0
spawn sh -c {echo "BUILD SUCCESSFUL"}
expect {
"BUILD SUCCESSFUL\r" {
#various and sundry other code to run
exit 123
}
"BUILD FAILED\r" {
exit 56
}
}
'
$ echo $?
123
$ expect -c '
log_user 0
spawn sh -c {echo "BUILD FAILED"}
expect {
"BUILD SUCCESSFUL\r" {
#various and sundry other code to run
exit 123
}
"BUILD FAILED\r" {
exit 56
}
}
'
$ echo $?
56
The issue was that nesting expect statements doesn't seem to work, so instead of the posted code, the following works:
#!/usr/bin/expect -f
set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
set timeout -1
spawn $env(SHELL)
match_max 100000
expect "~\$ "
send -- "sudo su\r"
expect "/home/ubuntu# "
send -- "cd ../../opt/application/"
send -- "\r"
expect "/opt/application# "
send -- "./buildwar.sh \r"
expect {
"BUILD SUCCESSFUL\r" {
send -- "su appuser\r"
}
"BUILD FAILED\r" {
exit 1
}
}
expect "/opt/application\$ "
send -- "../../home/ubuntu/shutdown.sh \r"
expect "\"outcome\" => \"success\"}"
send -- "exit\r"
expect "/opt/application# "
send -- "./deploywar.sh \r"
expect "BUILD SUCCESSFUL"
send -- "su appuser\r"
expect "/opt/application\$ "
send -- "../../home/ubuntu/startup.sh \r"
expect "Deployed \"application.war\""
send -- "exit\r"
send -- "exit\r"
send -- "exit\r"
You need to match against \n - though it won't matter if you just omit it.

Expect script error missing close-brackets

Hi here is my expect script:
#!/usr/local/bin/expect -f
set force_conservative 0 ;# set to 1 to force conservative mode even if
;# script wasn't run conservatively originally
if {$force_conservative} {
set send_slow {1 .1}
proc send {ignore arg} {
sleep .1
exp_send -s -- $arg
}
}
set timeout -1
spawn $env(SHELL)
match_max 100000
send -- "ssh IP_addr\r"
expect -exact "password: "
send -- "something\r"
expect -exact "\r"
#expect -exact "Entering server port, ..... type ^z for port menu."
send -- "\r"
expect -exact "login: "
send -- "admin\r"
expect -exact "password: "
send -- "something\r"
expect -exact "something > "
send -- "reboot\r"
expect -exact "REBOOT THE SYSTEM? (y or n): "
send -- "y\r"
expect -exact "SYSTEM REBOOTING!\r"
set no 20
for {set i 1} {$i < $no} {incr i 1} {
send -- "^[-"
}
expect -exact "\/----Enter Password----\\"
expec eof
I want to send escape and hyphen character multiple times until I receive "/----Enter Password-----\ prompt. But I'm receiving following error at this line:
missing close-bracket
while executing
"'send -- "^[-"'
"
("for" body line 2)
invoked from within
"for {set i 1} {$i < $no} {incr i 1} {
'send -- "^[-"'
}"
(file "script_auto.exp" line 31)
I'm newbie to expect. Kindly let me know what does that error mean and how can I resolve it.
expect is an extension of the Tcl language. In Tcl, square brackets are used for command substitution, exactly the way backticks are used in posix shells.
Change
send -- "^[-"
to
send -- {^[-}
The curly braces prevent command substitution, so the open bracket is seen as just a plain character.

expect script to ssh returns invalid command name

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

how to get the return code of the binary sftp when i'am Use expect in bash script to provide password to SFTP Command

I'm trying to use expect in an bash script to provide the SFTP password and put other commands.
I'am try to get the return code of binary SFTP .
My test script :
#!/bin/bash
USER=$1
HOST=$2
PASSWD=$3
PORT=$4
FILEIN=$5
FILEOUT=$6
ACTION=$7
CR_FTP=`/usr/bin/expect <<EOF | tee -a log.log
spawn sftp -v -oPort=$PORT $USER#$HOST
expect "password:"
send "$PASSWD\r"
expect "sftp>"
send "ls\r"
expect "sftp>"
send "$ACTION $FILEIN $FILEOUT\r"
expect "sftp>"
send "bye\r"
EOF`
echo " -------------------- $CR_FTP --------------------------"
...
send "bye\r"
expect eof
set details [wait]
puts "sftp exit status=[lindex $details 3]"
EOF`
See http://www.tcl.tk/man/expect5.31/expect.1.html

Resources