红宝石系统命令检查退出代码


106

我在ruby中有很多系统调用,例如以下代码,我想同时检查它们的退出代码,以便在该命令失败时退出我的脚本。

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

我想要类似的东西

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

那有可能吗?

我已经尝试了一些类似的方法,但是也没有用。

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

要么

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


在上面的示例中,exit_code将为字符串- "0\n""1\n",因此exit_code != 0将始终为true
dgmstuart

Answers:


166

文档中

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

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

此外

错误状态在中可用$?

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

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

2
以及如何将其输出(不是退出代码)捕获到变量?
アレックス

如果您在Rails控制台中进行测试,请记住您可能会失去$?的价值。因此,您需要将其捕获为REPL命令的一部分 [10] pry(main)> system("touch /root/test 2> /dev/null") => false [11] pry(main)> $?.exitstatus => 0 [12] pry(main)> system("touch /root/test 2> /dev/null"); $?.exitstatus => 1
lardcanoe 2015年

,和system反引号的另一个很好的比较%x,并exec在此处提供:stackoverflow.com/questions/6338908/…–
汤姆·哈里森

38

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

$?的一些有用方法 目的:

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

1
随着Rubocop的帮助下,我才发现原来可读别名$?$CHILD_STATUS
RajaRaviVarma

26

systemfalse如果命令的退出代码为非零,则返回,或者nil如果没有命令。

因此

system( "foo" ) or exit

要么

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

应该工作,并且合理简洁。


6

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

exit_code = system("ruby test.rb")

请记住,每次system调用或等效调用(包括反引号方法)都将生成一个新的外壳程序,因此无法捕获先前外壳程序环境的结果。在这种情况下exit_codetrue如果一切顺利,nil否则。

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


2
Open3.capture3是用于此类任务的一种特别简便的方法。
Tin Man

6

一种方法是使用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

到目前为止,这是我要实现的目标,非常简单明了。谢谢
mochadwi
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.