Bash expect/TCL脚本已损坏
我有一个Bash脚本,它在一个单独的函数中包含一个expect/TCL EOF脚本。expect脚本退出时可能有0-4个退出代码,这取决于expect/TCL脚本从远程设备确定的内容,并且在if。。。埃利夫。。。else语句我根据expect/TCL函数中的退出代码向变量写入特定字符串。然后将控制传递回Bash脚本,其中case块在所述变量包含的字符串上运行 我遇到的问题是,我的Bash函数(包含expect/TCL脚本)没有很好地捕获退出代码3,因为我可以看到日志文件条目正确写入日志文件,但是如果我回显退出代码的值,当情况应该是3时,它实际上捕捉到一个零,因此我的case语句没有准确地切换 你能找到窃听器吗 为了保持文章的简洁性和具体性,我将脚本切分为以下几个部分,因此假设周围的代码运行正常Bash expect/TCL脚本已损坏,bash,tcl,expect,Bash,Tcl,Expect,我有一个Bash脚本,它在一个单独的函数中包含一个expect/TCL EOF脚本。expect脚本退出时可能有0-4个退出代码,这取决于expect/TCL脚本从远程设备确定的内容,并且在if。。。埃利夫。。。else语句我根据expect/TCL函数中的退出代码向变量写入特定字符串。然后将控制传递回Bash脚本,其中case块在所述变量包含的字符串上运行 我遇到的问题是,我的Bash函数(包含expect/TCL脚本)没有很好地捕获退出代码3,因为我可以看到日志文件条目正确写入日志文件,但是
function myTclFunc()
{
/usr/bin/expect<<EOF
proc log_msg {msg {to_stdout no}} {
set log_line "[timestamp -format {[%d/%m/%Y @ %T]}] \$msg"
set fh [open ~/mylogfile.log a]
puts \$fh \$log_line
close \$fh
if {\$to_stdout} {puts \$log_line}
}
;#exp_internal 1
set timeout 5
set send_human {.1 .3 1 .05 2}
spawn ssh -o "StrictHostKeyChecking no" "[USER]@$1"
expect {
"password: " { send -h "[MY_PASSWD]\r" }
timeout { log_msg "A RELEVANT STRING TO LOG $1 / $2"; exit 1 }
}
set timeout 3
sleep 1 ;
send -h "[COMMAND A]\r" ;
expect {
timeout { exit 1 }
-re {\m\d{1,}(\.\d{1,}){3}\M}
}
if { ! [regexp {192\.[0-9]{1,3}\.{2}[0-9]{1,3}} $expect_out(0,string)]} {
send -h "[COMMAND B]\r" ;
}
expect {
"[STRING 1]" {
send -h "[COMMAND C]\r" ;
log_msg "Problem F on $1 / $2" ;
exit 3
}
"[STRING 2]" {
send -h "[COMMAND D]\r" ;
sleep 1 ;
send -h "[COMMAND E]\r" ;
send -h "\r" ;
puts "\r"
;#exit 0
}
}
expect eof
EOF
if [[ $? -eq 0 ]]; then
passBack="GOOD";
elif [[ $? -eq 3 ]]; then
passBack="BAD";
else
passBack="TIMEOUT";
fi;
}
[...snipped code...]
myTclFunc $myVar $1
case "$passBack" in
GOOD)
echo ""
exit 0
;;
BAD)
echo ""
exit 4
;;
CHECK)
echo ""
exit 3
;;
esac;
[...snipped code...]
壳牌和Tcl的混合有时会有点棘手。特别是,您希望将\传递到正则表达式引擎中的一些位置,在带有不带引号分隔符的here文档中。幸运的是,你把REs放在括号里,所以它只是让人困惑,而不是超级困惑 bash文档的相关部分说明: 这里有文件 这种类型的重定向指示shell从当前源读取输入,直到看到一行只包含单词,没有尾随空格。然后,读取到该点的所有行将用作命令的标准输入 此处文件的格式为:
<<[-]word
here-document
delimiter
哦,在整个脚本中,您还需要\\r如上所述,而不是\r
我认为将脚本分成两个文件会更容易,一个只是Bash代码,另一个只是Tcl代码,至少在您开发它时是这样。这样,你就可以使事情顺利进行,而不必在引用的许多层面上大惊小怪。现在替换的内容可以作为参数传递给脚本
将所有内容重新打包时,bash的printf%q可能会有所帮助。它会产生一些难以阅读的内容,但毕竟这是一个打包操作
关于错误代码呢?那里的问题更简单;测试本身-[$?-eq 0]]-设置错误代码。您必须将其保存到适当的变量中,然后根据该变量进行测试
在这里,检查这些简化的案例:
bash-3.2$ ( exit 2 ); if [[ $? -eq 0 ]]; then echo ok; elif [[ $? -eq 2 ]]; then echo good; else echo bad; fi
bad
bash-3.2$ ( exit 2 ); echo $?; if [[ $? -eq 0 ]]; then echo ok; elif [[ $? -eq 2 ]]; then echo good; else echo bad; fi
2
ok
bash-3.2$ ( exit 2 ); code=$?; echo $code; if [[ $code -eq 0 ]]; then echo ok; elif [[ $code -eq 2 ]]; then echo good; else echo bad; fi
2
good
第一个是你现在正在做的事情,第二个显示了它是多么的不明显——插入的回声改变了结果——第三个显示了如何处理它——在这里将值存储在代码中,但名称并不是那么特别。有用,虽然不幸的是,我仍然看到退出代码3没有被捕获的问题。@junky叔叔哈;经典的bash问题。你还需要解决其他问题……啊,我明白了。我很惊讶我在奥雷利的书《Shell脚本》中没有包括这个。。。谢谢,我将进行测试。我将确保从ssh会话中退出条件“3”和可能的“2”,以便您从脚本中获得返回代码,而不是ssh会话。因此,换句话说,如果登录,请确保您的expect脚本向远程计算机发送退出\n\r。不过,我已经处理了这个问题。
bash-3.2$ ( exit 2 ); if [[ $? -eq 0 ]]; then echo ok; elif [[ $? -eq 2 ]]; then echo good; else echo bad; fi
bad
bash-3.2$ ( exit 2 ); echo $?; if [[ $? -eq 0 ]]; then echo ok; elif [[ $? -eq 2 ]]; then echo good; else echo bad; fi
2
ok
bash-3.2$ ( exit 2 ); code=$?; echo $code; if [[ $code -eq 0 ]]; then echo ok; elif [[ $code -eq 2 ]]; then echo good; else echo bad; fi
2
good