我正在使用Ruby通过以下方式调用Shell脚本:
%x[ /root/script.sh -k -m -l -w -p]
exitCode = %x[echo $?]
if exitCode != 0
do something
else
do something else
end
我的问题是,即使我强制脚本失败,退出代码也始终等于0。 如何正确获取脚本的退出代码?
编辑:
好吧,今天早上来了,开始深入研究脚本,因为我无法获得除0以外的任何错误代码。脚本看起来像这样...
failed() {
if ["$1" -ne 0 ] ; then
echo"$2 failed. INSTALLATION FAILED! Exiting.";
exit 1;
fi
}
{
function 1
function 2..
function ..20
} | tee -a logFile.log
因此,脚本运行的最后一件事始终是此日志文件,这意味着我从未获得真正的退出代码。
相关:从Ruby调用shell命令。您可以执行exitCode = $?.exitstatus
我只是尝试过,我得到了TypeError,没有将Integer隐式转换为String。所以我尝试做exitCode = $ ?. exitstatus.to_i虽然我仍然遇到相同的错误
有趣。 ruby -e %x[rootscript.sh -k -m -l -w -p]; exitCode=$?.exitstatus; print exitCode也会失败吗?
你们两个走错了路。使用反引号时,OP的当前代码包含一个String(可能是0),而不是Integer退出状态。调用#class就可以了。
哦,我的意图是建议删除exitCode = %x[echo $?]并添加exitCode = $?.exitstatus。
红宝石系统命令检查出口代码的可能重复项
也许我应该指出这一点,我认为这并不重要,但是此代码正在通过Chef运行。我尝试了重复的答案,即使失败了,我仍然得到true并为$返回0?和$ ?. exitstatus为0。我开始认为这可能与脚本有关,因为它的长度超过3,000行,而我并未编写。我略过了它,当它失败时应该有一个退出代码1,但是在尝试了所有这些不同的方法而没有成功之后,我现在想知道。
在您的Ruby代码中,您一个接一个地创建了两个单独的(不相关的)进程。第一个过程运行script.sh,收集输出并丢弃(最好将system重定向到devnull而不是%x使用。
回声是真实的;检查最后的过程
怎么了
当前的代码几乎总是将其if语句评估为true,因为/bin/echo或shell内置的echo返回成功,除非关闭标准输出或发生其他错误。考虑以下Bash代码段:
echo `false`; echo $? # 0
echo >&-; echo $? # 1
另外,在您当前的代码中,exitCode是一个String而不是Integer。系统已为它分配了echo命令的标准输出,因此在尝试进行有效比较之前,必须在其上调用Kernel#Integer或String#to_i以强制转换该变量。例如,考虑以下Ruby:
`echo $?`.class #=> String
"0" == 0 #=> false
"0".to_i == 0 #=> true
如何解决一般情况
您需要直接测试退出状态,或检查捕获的输出。例如,在Ruby中,您可以使用以下命令测试/ bin / false命令的最后状态:
captured_output = `/bin/false`
$?.exitstatus
#=> 1
修正您的特定示例
如果您对以上内容一无所知,则可以通过去除所有不必要的内容来修复代码。根据您的示例,您不需要临时变量,也不需要存储标准输出。除非您要评估特定的非零退出状态,否则您甚至不需要直接检查流程状态,甚至不需要使用相等性语句。
遵循KISS原则,并仅评估Kernel#system调用的真实性。例如:
# Just call system if you don't care about the output.
# The result will be true, false, or nil.
if system('/root/script.sh -k -m -l -w -p')
'clean exit'
else
"non-zero exit: #{$?}"
end
我似乎仍然无法使它正常工作%x [/root/script.sh -k -m -l -w -p] capture_output = false将$ ?. exitstatus仍然返回为0。
您不应该使用%x。 查看CodeGnome提供的代码。 我建议对他的代码进行的唯一更改是执行system(rootscript.sh -k -m -l -w -p >devnull),因为您对正在执行的脚本的实际标准输出不感兴趣。