【发布时间】:2015-12-21 04:15:08
【问题描述】:
我正在尝试弄清楚如何持续监控我在我的 Expect 脚本中生成的自动 SSH 会话的 shell 错误。有没有办法让后台进程不断在我的 SSH 会话的输出中搜索“-ksh:”?
在 KSH 中,我会简单地捕获 ERR 信号,但 ERR 在 Expect 中不是有效的信号类型。关键是我想监控 shell 错误,这样我就可以通过我的退出处理程序,而不是让 Expect 脚本继续执行。
下面是我的一个 shell 函数/期望脚本的 sn-p。专门的 Expect 程序已被排除在外,因为它们与问题无关。这个特定的 Expect 脚本生成和 SSH 会话到合作伙伴服务器,并源/运行几个用户定义的 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="$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
}
【问题讨论】:
-
显示您的代码会很有帮助。
-
@GlennJackman 我添加了我的期望脚本之一。这是许多功能/预期脚本之一,它们协同工作以自动处理成对配置中两台服务器上的软件安装。在此功能运行之前,“主”服务器的配置文件已通过 SCP 发送给合作伙伴。配置文件将在伙伴上修改以用于安装,然后获取设置环境。获取配置文件后,将运行各个函数。
-
@GlennJackman 我在搜索类似问题的过程中看到了您曾推荐给一位用户使用
lassign [wait]来检测是否发生错误。我知道我有一个足够旧的 expect 版本, lassign 不是一个选项。我必须使用foreach {pid spawnid os_error_flag value} [wait] break并检查os_error_flag是否返回0。但是,我对在Expect 中编程还不够新,我不确定在这种情况下是否可以捕获任何shell 错误并退出退出处理程序,或者我将如何实现它。 -
在开始 run_functions 之前,定义一个
expect_after模式来查找 shell 错误字符串。像expect_after "err" { call my cleanup code }这样的东西。 expect_after 基本上将模式和操作(或多个)附加到后面的每个expect命令。 -
@GlennJackman 你会在调用run_functions之前定义expect_after,还是在expect -re $prompt之前成功连接到合作伙伴服务器之后这样做有意义?然后它会将模式和操作附加到 SSH 会话期间发生的所有预期命令,对吗?
标签: ssh error-handling ksh expect