在子shell中退出ruby而不杀死父shell



我有一个Ruby程序a,它调用Ruby程序b:

 system("ruby programB.rb <parameters>")

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

然而,exit()abort()杀死子shell和父,我无法让Process.kill("SIGTERM",0)在程序b中工作(不幸的是,这是在Windows上)。我使用的是ruby 1.9.2

如何终止程序b而不同时终止程序a ?

如果常规的system调用没有切割它,通常的方法是做这样的事情:

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

fork操作为您提供了一个可以杀死的进程标识符。system会阻塞,直到子进程返回,所以在父进程中对kill的任何调用只会影响父进程。

遗憾的是,Windows中没有fork,但有其他选择可以实现相同的功能。

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来简化。

对我来说唯一可靠的方法是:

kill -INT $$

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

相关内容

  • 没有找到相关文章

最新更新