在没有杀死父母的情况下退出子弹壳中的红宝石

时间:2012-12-22 01:27:20

标签: ruby termination subshell

我有Ruby programA,它用:

调用Ruby programB
 system("ruby programB.rb <parameters>")

在某些情况下,我希望programB终止其操作(以及相关的子shell),但允许programA继续使用下一组参数。

然而,exit()abort()同时杀死了子shell和父级,我无法让Process.kill("SIGTERM",0)在programB中工作(不幸的是,这是在Windows上)。我正在运行ruby 1.9.2。

如何在不杀死programA的情况下终止programB?

3 个答案:

答案 0 :(得分:3)

如果常规的system电话没有削减它,通常的方法是做这样的事情:

pid = fork do
  exec("ruby programB.rb ...")
end

kill("SIGTERM", pid)

fork操作为您提供了可以杀死的进程标识符。 system将阻止子进程返回,因此对父进程中的kill的任何调用都只会影响父进程。

不幸的是,Windows中没有fork,但有alternatives可以达到同样的效果。

答案 1 :(得分:2)

根据我的经验,

exit()abort()不会杀死父级,至少不会杀死Mac OS和Linux。

尝试将其另存为abort.rb

puts RUBY_VERSION
puts `date`
puts 'aborting'
abort

这是exit.rb

puts RUBY_VERSION
puts `date`
puts 'exiting'
exit

然后将此test.rb保存在同一目录中并运行它:

puts `ruby exit.rb`
puts `ruby abort.rb`

在我的系统上,我看到:

1.9.3
Fri Dec 21 22:17:12 MST 2012
exiting
1.9.3
Fri Dec 21 22:17:12 MST 2012
aborting

他们确实退出子shell中当前运行的脚本,然后退出因为它不是登录shell,并且可以设置一个对调用程序很重要的返回状态,但是我还没有看到它们被杀掉父母。

如果你需要捕获STDERR,使用反引号或%x将无效。如果您需要知道返回了什么状态代码,或者STDERR是否返回了任何内容,我建议您使用Open3.capture3来简化。

答案 2 :(得分:0)

对我来说唯一可靠的是:

kill -INT $$

它可靠地杀死脚本并且只杀死脚本,即使它是来自命令行的源代码。请注意,我正在运行GNU bash,版本4.4.12(1)-release(x86_64-apple-darwin15.6.0);我不记得这是否适用于bash 3.x