Вы не хотите использовать system
, поскольку он ожидает завершения процесса. Вместо этого вы можете использовать spawn
, а затем ждать процессов (чтобы избежать зомби). Затем, когда вы хотите выйти, отправьте SIGTERM своим порожденным процессам. Вы также можете использовать fork
для запуска ваших дочерних процессов, но spawn
, вероятно, проще, если вы используете внешние программы.
Вы также можете использовать группы процессов вместо отслеживания всех идентификаторов процессов, тогда один вызов 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
Если вы запустите это в одном терминале, а затем убьете его из другого (используя команду kill
оболочки), вы увидите, что дети также были убиты. Если вы уберете строку «перенаправить этот сигнал всей группе процессов» Signal.trap
, тогда простой SIGTERM оставит детей в рабочем состоянии.
Все это предполагает, что вы работаете в какой-то системе Unixy (например, Linux или OSX), YMMV где-либо еще.