我有一个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上是否有效