您不想使用system,因为它会等待进程完成。您可以使用 spawn 代替,然后将 wait 用于进程(以避免僵尸)。然后,当您想退出时,向您生成的进程发送一个 SIGTERM。您也可以使用fork 来启动您的子进程,但如果您使用外部程序,spawn 可能更容易。
您也可以使用进程组而不是跟踪所有进程 ID,然后一个 Process.kill('TERM', -process_group_id) 调用就可以解决问题。您的子进程应该在同一个进程组中结束,但如果需要,可以使用 Process.setpgid。
这是一个使用 fork 的示例(这样更容易将其全部包装在一个包中)。
def launch(id, sleep_for)
pid = Process.fork do
while(true)
puts "#{id}, pgid = #{Process.getpgid(Process.pid())}, pid = #{Process.pid()}"
sleep(sleep_for)
end
end
# No zombie processes please.
Process.wait(pid, Process::WNOHANG)
pid
end
# These just forward the signals to the whole process group and
# then immediately exit.
pgid = Process.getpgid(Process.pid())
Signal.trap('TERM') { Process.kill('TERM', -pgid); exit }
Signal.trap('INT' ) { Process.kill('INT', -pgid); exit }
launch('a', 5)
launch('b', 3)
while(true)
puts "p, pgid = #{Process.getpgid(Process.pid())}, pid = #{Process.pid()}"
sleep 2
end
如果你在一个终端中运行它,然后从另一个终端中杀死它(使用 shell 的 kill 命令),你会看到孩子们也被杀死了。如果您删除“将此信号转发给整个进程组”Signal.trap 的东西,那么一个简单的 SIGTERM 将使子进程仍在运行。
所有这些都假设您正在使用某种 Unixy 系统(例如 Linux 或 OSX),YMMV 其他任何地方。