监视 Expect 脚本中 shell 错误的衍生进程
Monitor spawned process for shell errors in Expect script
我想弄清楚如何持续监控我在 Expect 脚本中生成的自动 SSH 会话是否有 shell 错误。有没有办法让后台进程持续搜索我的 SSH 会话的输出以查找“-ksh:”?
在 KSH 中,我会简单地捕获 ERR 信号,但 ERR 在 Expect 中不是有效的信号类型。关键是我想监视 shell 错误,这样我就可以通过我的退出处理程序而不是 Expect 脚本继续执行。
下面是我的一个 shell functions/expect 脚本的片段。排除了专门的 Expect 程序,因为它们与问题无关。这个特定的 Expect 脚本生成和 SSH 会话到合作伙伴服务器和 sources/runs 几个用户定义的 shell 函数。当获取并执行 init_log 函数时,将创建日志文件并将 STDOUT/STDERR 重定向到这些日志 - 因此需要 tee /dev/tty 命令以便我可以从函数中看到 STDOUT我在伙伴服务器上 运行。我不确定我是否应该暂时将 STDERR 重定向到屏幕并在我的每个期望块中期望“-ksh:”,或者如果 shell 错误发生在我的 SSH 会话期间的任何时间点。
function exp_run_funcs {
# Check for DEBUG mode
[[ -n $DEBUG ]] && typeset PS4="[=11=]: " && set -x
# Log status message
log_stdout [=11=] "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 [=11=]\"; 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
}
评论中提到的我的脚本中的固有重定向需要更多与这个问题无关的工作,所以我将简单地 post 预期 KSH 错误的答案。
在 ### Source the configuration file ###
部分之前,我添加了以下内容:
### Expect any KSH or function errors ###
expect_before -re "-ksh(.*): | (.*):(.*): " {set status 12; exit $status}
这实质上是将一个 expect -re 块添加到此代码段之后的所有 expect 块,包括过程中的那些。当出现 KSH 或 shell 函数错误时,它将期望出现通常看到的语法。
我想弄清楚如何持续监控我在 Expect 脚本中生成的自动 SSH 会话是否有 shell 错误。有没有办法让后台进程持续搜索我的 SSH 会话的输出以查找“-ksh:”?
在 KSH 中,我会简单地捕获 ERR 信号,但 ERR 在 Expect 中不是有效的信号类型。关键是我想监视 shell 错误,这样我就可以通过我的退出处理程序而不是 Expect 脚本继续执行。
下面是我的一个 shell functions/expect 脚本的片段。排除了专门的 Expect 程序,因为它们与问题无关。这个特定的 Expect 脚本生成和 SSH 会话到合作伙伴服务器和 sources/runs 几个用户定义的 shell 函数。当获取并执行 init_log 函数时,将创建日志文件并将 STDOUT/STDERR 重定向到这些日志 - 因此需要 tee /dev/tty 命令以便我可以从函数中看到 STDOUT我在伙伴服务器上 运行。我不确定我是否应该暂时将 STDERR 重定向到屏幕并在我的每个期望块中期望“-ksh:”,或者如果 shell 错误发生在我的 SSH 会话期间的任何时间点。
function exp_run_funcs {
# Check for DEBUG mode
[[ -n $DEBUG ]] && typeset PS4="[=11=]: " && set -x
# Log status message
log_stdout [=11=] "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 [=11=]\"; 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
}
评论中提到的我的脚本中的固有重定向需要更多与这个问题无关的工作,所以我将简单地 post 预期 KSH 错误的答案。
在 ### Source the configuration file ###
部分之前,我添加了以下内容:
### Expect any KSH or function errors ###
expect_before -re "-ksh(.*): | (.*):(.*): " {set status 12; exit $status}
这实质上是将一个 expect -re 块添加到此代码段之后的所有 expect 块,包括过程中的那些。当出现 KSH 或 shell 函数错误时,它将期望出现通常看到的语法。