检查出口代码

我在 ruby 中有很多系统调用,比如下面这些,我想同时检查它们的退出代码,这样如果命令失败,我的脚本就会退出。

system("VBoxManage createvm --name test1")
system("ruby test.rb")

我想要

system("VBoxManage createvm --name test1", 0) < ——第二个参数检查退出代码并确认系统调用成功,如果不成功,它将引发错误或执行类似的操作。

Is that possible at all?

我尝试过类似的方法,但也没有成功。

system("ruby test.rb")
system("echo $?")

或者

`ruby test.rb`
exit_code = `echo $?`
if exit_code != 0
raise 'Exit code is not zero'
end
102186 次浏览

如果命令有非零退出代码,则 system返回 false; 如果没有命令,则返回 nil

因此

system( "foo" ) or exit

或者

system( "foo" ) or raise "Something went wrong with foo"

应该工作,并合理简洁。

您没有捕获 system调用的结果,这是返回结果代码的地方:

exit_code = system("ruby test.rb")

记住每个 system调用或等效调用(包括 backtick-method)都会生成一个新的 shell,因此不可能捕获前一个 shell 环境的结果。在这种情况下,如果一切正常,则 exit_codetrue,否则为 nil

popen3命令提供了更多的底层细节。

From the documentation:

如果命令退出状态为零,则 system 返回 true 非零退出状态。如果命令执行失败,返回 nil

system("unknown command")     #=> nil
system("echo foo")            #=> true
system("echo foo | grep bar") #=> false

Furthermore

$?中有一个错误状态。

system("VBoxManage createvm --invalid-option")


$?             #=> #<Process::Status: pid 9926 exit 2>
$?.exitstatus  #=> 2

一种方法是使用 and&&将它们链接起来:

system("VBoxManage createvm --name test1") and system("ruby test.rb")

如果第一个调用失败,第二个调用将不会运行。

你可以把它们包装在一个 if ()里,这样就可以给你一些流程控制:

if (
system("VBoxManage createvm --name test1") &&
system("ruby test.rb")
)
# do something
else
# do something with $?
end

对我来说,我更喜欢使用“来调用 shell 命令并检查 $?来获得进程状态。$?是一个进程状态对象,您可以从该对象获得命令的进程信息,包括: 状态代码、执行状态、 pid 等。

$? 对象的一些有用的方法:

   $?.exitstatus => return error code
$?.success? => return true if error code is 0, otherwise false
$?.pid => created process pid

我想要

system("VBoxManage createvm --name test1", 0) < ——第二个参数检查退出代码并确认系统调用成功,如果不成功,它将引发错误或执行类似的操作。

可以将 exception: true添加到 system调用中,以在非0退出代码上引发错误。

For example, consider this small wrapper around system which prints the command (similar to bash -x, fails if there's a non 0 exit code (like bash -e) and returns the actual exit code:

def sys(cmd, *args, **kwargs)
puts("\e[1m\e[33m#{cmd} #{args}\e[0m\e[22m")
system(cmd, *args, exception: true, **kwargs)
return $?.exitstatus
end

被称为: sys("hg", "update") 如果要调用对退出代码使用不同约定的程序,可以禁止引发异常:

sys("robocopy", src, dst, "/COPYALL", "/E", "/R:0", "/DCOPY:T", exception: false)

You can also suppress stdout and stderr for noisy programs:

sys("hg", "update", "default", :out => File::NULL, :err => File::NULL)