Как я могу запустить и забыть процесс в Perl?

Может кто-нибудь сказать мне, как запустить и забыть процесс в Perl? Я уже посмотрел на ruby: как запустить и забыть подпроцесс? за то же самое в Ruby.

4 ответа

Решение

Из ответа perlfaq8 на Как запустить процесс в фоновом режиме?


Несколько модулей могут запускать другие процессы, которые не блокируют вашу Perl-программу. Вы можете использовать IPC::Open3, Parallel::Jobs, IPC::Run и некоторые модули POE. Смотрите CPAN для более подробной информации.

Вы также можете использовать

system("cmd &")

или вы можете использовать fork, как описано в "fork" в perlfunc, с дополнительными примерами в perlipc. Некоторые вещи, о которых следует знать, если вы работаете в Unix-подобной системе:

STDIN, STDOUT и STDERR являются общими

И основной процесс, и фоновый процесс ("дочерний" процесс) используют одни и те же файловые дескрипторы STDIN, STDOUT и STDERR. Если оба пытаются получить к ним доступ сразу, могут случиться странные вещи. Вы можете закрыть или снова открыть их для ребенка. Вы можете обойти это с помощью "открытия" канала (см. "Открытие" в perlfunc), но в некоторых системах это означает, что дочерний процесс не может пережить родительский.

сигналы

Вам придется поймать сигнал SIGCHLD и, возможно, SIGPIPE. SIGCHLD отправляется после завершения фонового процесса. SIGPIPE отправляется, когда вы пишете в файловый дескриптор, чей дочерний процесс закрыт (незаданный SIGPIPE может вызвать молчаливое завершение вашей программы). Это не проблема с "system (" cmd & ")".

Zombies

Вы должны быть готовы "пожинать" дочерний процесс после его завершения.

   $SIG{CHLD} = sub { wait };

   $SIG{CHLD} = 'IGNORE';

Вы также можете использовать двойную вилку. Вы немедленно ждете () своего первого ребенка, и демон init будет ждать () вашего внука, как только он выйдет.

   unless ($pid = fork) {
       unless (fork) {
           exec "what you really wanna do";
           die "exec failed!";
       }
       exit 0;
   }
   waitpid($pid, 0);

Посмотрите "Сигналы" в perlipc для других примеров кода, чтобы сделать это. Зомби не проблема с "system("prog &")".

Если вы хотите демонизировать ваш Perl-скрипт, я бы заглянул в Proc:: Daemon.

Если вы хотите, чтобы "дочерний" процесс сторожевого механизма исчезал при выходе из "родительского" процесса, вам не нужно, чтобы родительский процесс "запускал и забывал" дочерний процесс. Вам нужно либо выполнить форк (как описано Брайаном Д. Фой), либо передать PID родительского объекта ребенку (чтобы последний мог опрашивать таблицу процессов - не рекомендуется).

Ну, вы не должны использовать system() насколько я понимаю, этот вызов будет ожидать возврата функции, прежде чем продолжить выполнение. Я просто выложил бы в linux и запустил процесс таким образом, хотя учтите, что этот способ вызовет новую копию оболочки, и поэтому, если вы ищете производительность, я бы не стал делать это в цикле, например:

process_name > /dev/null 2>&1 &;

Это запустит процесс перенаправления STDOUT а также STDERR в / dev / null.

Другие вопросы по тегам