Trying to spawn an SSH session to 1 or more of a branch locations devices, from within a single expect script.
I have a bash script which takes 3 args:
- the Expect script
- the Output directory for the results of the expect script
- the list of branch locations that i want to connect to
All the devices are mapped to DNS nodes, so site 1234 will have 1-5 devices I want. Lets say like 1234R, 1234FW1, 1234S1, and/or 1234S2.
The list of sites is pulled from a file passed to the bash wrapper. The site number is passed to the expect script from this file.
The expect script has 5 list objects, and 5 if statementes. If the list is not empty, process the commands for in the list. Each list, corresponds to a device type I want to connect to at a branch location (They have to be different because the CLI prompt is different, and we don't want to accidentally run the commands on a device that we did not intend to)
My problem is that, if my expect script is unable to process device 2/5, say because it is unreachable/offline, it stops processing the rest.
So if for site 1234 I wanted to process commands on device 2/5 (FW1) and device 4/5 (S1) but FW1 is offline, S1 is never processed.
I can't exit because that exits the entire script. I've tried using expect eof, close -i $spawn_id to close the global spawn_id, and even a timeout, but the process just gives me the same error everytime. I feel like I'm missing something super obvious.
Here's the Expect script:
#!/usr/bin/expect
#Purpose: SSH to remote juniper hosts and execute commands.
#Syntax: <script name> <site number> <username> <password>
global spawn_id;
global sess_id;
set cmds_R [ list \
]
set cmds_FW1 [ list \
"show system license" \
"exit" \
]
set cmds_10MB [ list \
]
set cmds_S1 [ list \
"show interfaces terse | no-more" \
"exit" \
]
set cmds_S2 [ list \
]
# Check for Primary Router commands
# If found, run Primary router commands.
if { $cmds_R != "" } {
proc _jgetRouterIPs {} {
set file [open router-list r]
while {![eof $file]} {
set buff [read $file]
}
close $file
return $buff
}
proc ssh2rtr { rtr usr pwd } {
spawn ssh -l $usr $rtr;
set sess_id $spawn_id;
set ppret [ processPrompts $rtr $usr $pwd $sess_id 0 ];
set timeout 60;
if { $ppret == 0 } {
return $spawn_id;
} else {
send_user "Failed to process prompts on R!!!";
}
}
proc processPrompts { rtr usr pwd sess_id status } {
set timeout 90;
set spawn_id $sess_id;
set fw_prompt {\n*@[0-9]{4}\-[A-Z]{2}\-R(>|#)\s};
if { $status < 2 } {
expect {
-re $fw_prompt { return 0;}
"no)?" { send "yes\r";
processPrompts $rtr $usr $pwd $sess_id 0;
}
"assword:" {
send "${pwd}\r";
if { $status} { return 1;}
processPrompts $rtr $usr $pwd $sess_id 1;
}
"ssh: Could not resolve hostname" {
send_user "\nDNS Error!!! Check Hostname and try again!\n"; return 10;
}
timeout { send_user "\nTimeout on SSH!!!\n"; return 8;} ;#no reponse from telnet/ssh
default { send_user "\nSSH Unknown Error!!!\n"; return 9;} ;#unknown error has occurred.
} ;#end expect
} ;#end if
}
set site [lindex $argv 0];
set fw "${site}R";
set usr [lindex $argv 1];
set pwd [lindex $argv 2];
set fw_prompt {\n*@[0-9]{4}\-[A-Z]{2}\-R(>|#)\s};
set yesorp {(\(yes\))|(-R(>|#))};
set timeout 90;
set sshret [ ssh2rtr $fw $usr $pwd ] ;
if { $sshret != 99 } {
set spawn_id $sshret;
} else {
send_user "Error Connecting...!!!";
}
foreach cmd $cmds_R {
send "${cmd}\r";
expect -re $fw_prompt;
}
} else {
send_user "\nNo commands for Router\n";
}
# Check for Backup Router commands
# If found, run Backup router commands.
if { $cmds_FW1 != "" } {
proc _jgetRouterIPs {} {
set file [open router-list r]
while {![eof $file]} {
set buff [read $file]
}
close $file
return $buff
}
proc ssh2rtr { rtr usr pwd } {
spawn ssh -l $usr $rtr;
set sess_id $spawn_id;
set ppret [ processPrompts $rtr $usr $pwd $sess_id 0 ];
set timeout 60;
if { $ppret == 0 } {
return $spawn_id;
} else {
send_user "Failed to process prompts on FW1!!!";
}
}
proc processPrompts { rtr usr pwd sess_id status } {
set timeout 90;
set spawn_id $sess_id;
set fw_prompt {\n*@[0-9]{4}\-[A-Z]{2}\-FW1(>|#)\s};
if { $status < 2 } {
expect {
-re $fw_prompt { return 0;}
"no)?" { send "yes\r";
processPrompts $rtr $usr $pwd $sess_id 0;
}
"assword:" {
send "${pwd}\r";
if { $status} { return 1;}
processPrompts $rtr $usr $pwd $sess_id 1;
}
"ssh: Could not resolve hostname" {
send_user "\nDNS Error!!! Check Hostname and try again!\n"; return 10;
}
timeout { send_user "\nTimeout on SSH!!!\n"; return 8;} ;#no reponse from telnet/ssh
default { send_user "\nSSH Unknown Error!!!\n"; return 9;} ;#unknown error has occurred.
} ;#end expect
} ;#end if
}
set site [lindex $argv 0];
set fw "${site}FW1";
set usr [lindex $argv 1];
set pwd [lindex $argv 2];
set fw_prompt {\n*@[0-9]{4}\-[A-Z]{2}\-FW1(>|#)\s};
set yesorp {(\(yes\))|(-FW1(>|#))};
set timeout 90;
set sshret [ ssh2rtr $fw $usr $pwd ] ;
if { $sshret != 99 } {
set spawn_id $sshret;
} else {
send_user "Error Connecting...!!!";
}
foreach cmd $cmds_FW1 {
send "${cmd}\r";
expect -re $fw_prompt;
}
} else {
send_user "\nNo commands for Backup FW1\n";
}
# Check for 10MB Router commands
# If found, run 10MB Router commands.
if { $cmds_10MB != "" } {
proc _jgetRouterIPs {} {
set file [open router-list r]
while {![eof $file]} {
set buff [read $file]
}
close $file
return $buff
}
proc ssh2rtr { rtr usr pwd } {
spawn ssh -l $usr $rtr;
set sess_id $spawn_id;
set ppret [ processPrompts $rtr $usr $pwd $sess_id 0 ];
if { $ppret == 0 } {
return $spawn_id;
} else {
send_user "Failed to process prompts on 10MB!!!";
close;
close -i $spawn_id;
}
}
proc processPrompts { rtr usr pwd sess_id status } {
set timeout 90;
set spawn_id $sess_id;
set fw_prompt {[a-z0-9]+@+[0-9]+([A-Za-z0-9-]{5,11})(>|#)};
if { $status < 2 } {
expect {
-re $fw_prompt { return 0;}
"no)?" { send "yes\r";
processPrompts $rtr $usr $pwd $sess_id 0;
}
"assword:" {
send "${pwd}\r";
if { $status} { return 1;}
processPrompts $rtr $usr $pwd $sess_id 1;
}
"ssh: Could not resolve hostname" {
send_user "\nDNS Error!!! Check Hostname and try again!\n"; return 10;
}
timeout { send_user "\nTimeout on SSH!!!\n"; return 8;} ;#no reponse from telnet/ssh
default { send_user "\nSSH Unknown Error!!!\n"; return 9;} ;#unknown error has occurred.
} ;#end expect
} ;#end if
}
set site [lindex $argv 0];
set fw "${site}R";
set usr [lindex $argv 1];
set pwd [lindex $argv 2];
set fw_prompt {[a-z0-9]+@+[0-9]+([A-Za-z0-9-]{5,11})(>|#)};
set yesorp {(\(yes\))|([A-Za-z0-9-]{5,11})(>|#)};
set timeout 90;
set sshret [ ssh2rtr $fw $usr $pwd ] ;
if { $sshret != 99 } {
set spawn_id $sshret;
} else {
send_user "Error Connecting...!!!";
}
foreach cmd $cmds_10MB {
send "${cmd}\r";
expect -re $fw_prompt;
}
} else {
send_user "\nNo commands for 10MB Router\n";
}
# Check for Switch 1 commands
# If found, run Switch 1 commands.
if { $cmds_S1 != "" } {
proc _jgetRouterIPs {} {
set file [open router-list r]
while {![eof $file]} {
set buff [read $file]
}
close $file
return $buff
}
proc ssh2rtr { rtr usr pwd } {
spawn ssh -l $usr $rtr;
set sess_id $spawn_id;
set ppret [ processPrompts $rtr $usr $pwd $sess_id 0 ];
if { $ppret == 0 } {
return $spawn_id;
} else {
send_user "Failed to process prompts on S1!!!";
close;
close -i $spawn_id;
}
}
proc processPrompts { rtr usr pwd sess_id status } {
set timeout 90;
set spawn_id $sess_id;
set fw_prompt {\n*@[0-9]{4}\-[A-Z]{2}\-S1(>|#)\s};
if { $status < 2 } {
expect {
-re $fw_prompt { return 0;}
"no)?" { send "yes\r";
processPrompts $rtr $usr $pwd $sess_id 0;
}
"assword:" {
send "${pwd}\r";
if { $status} { return 1;}
processPrompts $rtr $usr $pwd $sess_id 1;
}
"ssh: Could not resolve hostname" {
send_user "\nDNS Error!!! Check Hostname and try again!\n"; return 10;
}
timeout { send_user "\nTimeout on SSH!!!\n"; return 8;} ;#no reponse from telnet/ssh
default { send_user "\nSSH Unknown Error!!!\n"; return 9;} ;#unknown error has occurred.
} ;#end expect
} ;#end if
}
set site [lindex $argv 0];
set fw "${site}S1";
set usr [lindex $argv 1];
set pwd [lindex $argv 2];
set fw_prompt {\n*@[0-9]{4}\-[A-Z]{2}\-S1(>|#)\s};
set yesorp {(\(yes\))|(-S1(>|#))};
set timeout 90;
set sshret [ ssh2rtr $fw $usr $pwd ] ;
if { $sshret != 99 } {
set spawn_id $sshret;
} else {
send_user "Error Connecting...!!!";
}
foreach cmd $cmds_S1 {
send "${cmd}\r";
expect -re $fw_prompt;
}
} else {
send_user "\nNo commands for Switch 1\n";
}
# Check for Switch 2 commands
# If found, run Switch 2 commands.
if { $cmds_S2 != "" } {
proc _jgetRouterIPs {} {
set file [open router-list r]
while {![eof $file]} {
set buff [read $file]
}
close $file
return $buff
}
proc ssh2rtr { rtr usr pwd } {
spawn ssh -l $usr $rtr;
set sess_id $spawn_id;
set ppret [ processPrompts $rtr $usr $pwd $sess_id 0 ];
if { $ppret == 0 } {
return $spawn_id;
} else {
send_user "Failed to process prompts on S2!!!";
close;
close -i $spawn_id;
}
}
proc processPrompts { rtr usr pwd sess_id status } {
set timeout 90;
set spawn_id $sess_id;
set fw_prompt {\n*@[0-9]{4}\-[A-Z]{2}\-S2(>|#)\s};
if { $status < 2 } {
expect {
-re $fw_prompt { return 0;}
"no)?" { send "yes\r";
processPrompts $rtr $usr $pwd $sess_id 0;
}
"assword:" {
send "${pwd}\r";
if { $status} { return 1;}
processPrompts $rtr $usr $pwd $sess_id 1;
}
"ssh: Could not resolve hostname" {
send_user "\nDNS Error!!! Check Hostname and try again!\n"; return 10;
}
timeout { send_user "\nTimeout on SSH!!!\n"; return 8;} ;#no reponse from telnet/ssh
default { send_user "\nSSH Unknown Error!!!\n"; return 9;} ;#unknown error has occurred.
} ;#end expect
} ;#end if
}
set site [lindex $argv 0];
set fw "${site}S2";
set usr [lindex $argv 1];
set pwd [lindex $argv 2];
set fw_prompt {\n*@[0-9]{4}\-[A-Z]{2}\-S2(>|#)\s};
set yesorp {(\(yes\))|(-S2(>|#))};
set timeout 90;
set sshret [ ssh2rtr $fw $usr $pwd ] ;
if { $sshret != 99 } {
set spawn_id $sshret;
} else {
send_user "Error Connecting...!!!";
}
foreach cmd $cmds_S2 {
send "${cmd}\r";
expect -re $fw_prompt;
}
} else {
send_user "\nNo commands for Switch 2\n";
}
The output I get to the console when a device is unreachable is:
can not find channel named ""
while executing
"send "${cmd}\r""
("foreach" body line 2)
invoked from within
"foreach cmd $cmds_FW1 {
send "${cmd}\r";
expect -re $fw_prompt;
}"
invoked from within
"if { $cmds_FW1 != "" } {
proc _jgetRouterIPs {} {
set file [open router-list r]
while {![eof $file]} {
set buff [read $file]
}
close $file
return..."
(file "./show-sys-lic_FW1" line 157)
I want to process this more cleanly and output a message via send_user saying unable to process prompts, and then move on until all 5 if statements have been tested and completed.
Currently it will do the send_user in the else clause, but anything else I add there doesn't let me proceed past that first if/else statment. The script just exits.
if { $ppret == 0 } {
return $spawn_id;
} else {
send_user "Failed to process prompts on R!!!";
}
}
Aucun commentaire:
Enregistrer un commentaire