Ruby запускает два процесса, выводит результаты на терминал и безопасно завершает работу - PullRequest
1 голос
/ 21 августа 2011

В Ruby я использую систему («команда здесь»), которая постоянно следит за изменениями файлов, похожих на tail. Я бы хотел, чтобы моя программа продолжала работать, а не останавливаться при вызове system (). Есть ли способ в Ruby создать другой процесс, чтобы оба могли работать независимо, выводить результаты в терминал, а затем при выходе из программы удаляются все процессы, созданные в приложении?

Ответы [ 3 ]

2 голосов
/ 21 августа 2011

Вы не хотите использовать 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 где-либо еще.

2 голосов
/ 21 августа 2011

Просто объедините spawn и waitall:

spawn 'sleep 6'
spawn 'sleep 8'
Process.waitall
0 голосов
/ 21 августа 2011

Еще один голос за использование Spawn.Мы часто используем его в производстве, и он очень стабилен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...