I am trying to figure out how to continuously monitor an automated SSH session I spawned in my Expect script for shell errors. Is there a way to have a background process that continuously searches the output of my SSH session for "-ksh:"?
In KSH, I would simply trap ERR signals, but ERR is not a valid signal type in Expect. The point is that I'd like to monitor for shell errors so I can go through my exit handler rather than the Expect script continuing execution.
Below is a snippet from one of my shell functions/expect scripts. The specialized Expect procedures have been excluded, as they are not pertinent to the question. This particular Expect script spawns and SSH session to a partner server and sources/runs several user defined shell functions. When the init_log function is sourced and executed, log files are created and STDOUT/STDERR are redirected to those logs - hence the need for the tee /dev/tty command so that I can see STDOUT from the functions I am running on the partner server. I am not sure if I should temporarily redirect STDERR to the screen and expect "-ksh:" at each of my expect blocks, or if there is an easier and hopefully more robust method to monitor if a shell error occurs at any point during my SSH session.
function exp_run_funcs {
# Check for DEBUG mode
[[ -n $DEBUG ]] && typeset PS4="$0: " && set -x
# Log status message
log_stdout $0 "Running functions on the $rsvr server."
# Run functions on remote host
expect -c "set logdir $sai_logdir; set dlogfl $detailflnm;\
set ulogfl $usrflnm; set prgmfunc \"$program $0\"; set remsvr $rsvr;\
set user $usr; set host ${ip_ad[$rind]}; set pwd $pswd;\
set cfgfl $sai_cfgflnm; set sai_chksum \"$chksum\"" -c '
########## INITIALIZATION ##########
### Expect environment initialization ###
set timeout 15
log_user 0
set prompt "(%|#|>|\\\$) $"
set status 1 ; # Initialize status to failure
########## ESTABLISH SSH CONNECTION TO REMOTE SERVER ##########
spawn -noecho ssh $user@$host
if [catch "spawn ssh $user@$host" reason] {
puts "Failed to establish SSH connection\
to $remsvr server ($host): $reason.\n"
set status 3
exit $status
}
### Set responses for expected login prompts ###
expect {
-re "(.*)assword:" {
send "$pwd\r"
}
"you sure you want to continue connecting" {
send -s "yes\r"
exp_continue
}
timeout {
set status 4
exit $status
}
eof {
set status 5
exit $status
}
}
expect -re $prompt {
set timeout -1
### Source the configuration file ###
puts "Sourcing the configuration file on the\
$remsvr server.\n"
send ". $cfgfl\r"
if [catch "send \". \$cfgfl\r\"" reason] {
puts "Failed to source the configuration file:\
$reason.\n"
set status 9
exit $status
}
expect -re "(.*)config.ini\r\n(.*)$prompt"
### Run individual functions ###
set timeout 15
set tdir "$logdir/tmp"
set fcnlst "init_log init_env install_func\
srv_setup"
foreach fcn $fcnlst {
puts "Sourcing and running function $fcn.\n"
if {[run_function "$fcn"] != 0} {
exit $status
}
if {$fcn != "init_log"} {puts "\n"}
merge_logs
}
expect -re $ { set status 0 }
}
' | tee /dev/tty
}
lassign [wait]to detect if an error occurred. I know that I have an old enough version of expect that lassign isn't an option. I'd have to useforeach {pid spawnid os_error_flag value} [wait] breakand check ifos_error_flagreturns 0. However, I'm new enough to programming in Expect that I'm not sure if that would work in this case for catching any shell errors and exiting through the exit handler, or how I would go about implementing it. - legendmacexpect_afterpattern to look for shell error strings. Something likeexpect_after "err" { call my cleanup code }. expect_after basically appends the pattern and action (or more than one) to eachexpectcommand that comes after. - glenn jackman