使用 Ruby 调用 shell 脚本退出代码总是 returns 为 0

Using Ruby to call a shell script exit code always returns as 0

我正在使用 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 [ "" -ne 0 ] ; then
          echo " failed. INSTALLATION FAILED! Exiting.";
      exit 1;
    fi
}

{

function 1
function 2..
function ..20

} | tee -a logFile.log 

所以脚本运行的最后一件事总是这个日志文件,这意味着我永远不会得到真正的退出代码。

Echo True;而是检查你的最后一个过程

怎么了

您当前的代码几乎总是将其 if 语句评估为真,因为 /bin/echo 或 shell 内置 echo return 成功,除非标准输出已关闭或某些发生其他错误。考虑以下 Bash 片段:

echo `false`; echo $? # 0
echo >&-; echo $?     # 1

此外,在您当前的代码中,exitCode 是一个字符串,而不是一个整数。它被分配为 echo 命令的标准输出,因此在尝试进行有效比较之前,您必须对其调用 Kernel#Integer or String#to_i 以转换变量。例如,考虑以下 Ruby:

`echo $?`.class #=> String
"0" == 0        #=> false
"0".to_i == 0   #=> true

如何解决一般情况

您需要直接测试 exit status,或检查捕获的输出。例如,在 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