Как я могу сделать форк в Perl в разных скриптах? - PullRequest
1 голос
/ 29 октября 2010

У меня есть процесс в Perl, который создает другой с помощью системной команды , я оставляю его в памяти и передаю некоторые переменные, например:


my $var1 = "Hello";
my $var1 = "World";
system "./another_process.pl $var1 $var2 &";

Но системная командатолько возвращает результат, мне нужно получить PID.Я хочу сделать что-то вроде fork .Что я должен делать?Как я могу сделать что-то вроде форка, но в разных скриптах?

Заранее спасибо!

Ответы [ 4 ]

5 голосов
/ 29 октября 2010

Perl имеет функцию fork.

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


(предоставлено brian d foy)

Нет единого способа запуска кода в фоновом режиме, поэтому вам не нужно ждать его завершения, прежде чем ваша программа перейдет к другим задачам.,Управление процессами зависит от вашей конкретной операционной системы, и многие из методов находятся в perlipc.Может помочь несколько модулей CPAN, включая IPC::Open2 или IPC::Open3, IPC::Run, Parallel::Jobs,Parallel::ForkManager, POE, Proc::Background и Win32::Process.

Существует множество других модулей, которые вы можете использовать, поэтому проверьте эти пространства имен и для других опций.Если вы работаете в Unix-подобной системе, вам, возможно, удастся уйти с помощью системного вызова, где вы ставите & в конце команды:

    system("cmd &")

Вы также можете попробовать использовать fork, как описано в perlfunc (хотя это то же самое, что многие модули сделают для вас).

STDIN, STDOUT и STDERRshared

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

Сигналы

Вам придется ловить сигнал 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 &"). system("prog &").

3 голосов
/ 29 октября 2010

Это правда, что вы можете использовать fork / exec, но я думаю, что будет гораздо проще просто использовать форму канала open.Мало того, что возвращаемое значение - это pid, который вы ищете, вы можете подключиться либо к stdin, либо к stdout процесса, в зависимости от того, как вы открываете.Например:

open my $handle, "foo|";

вернет pid foo и соединит вас с stdout, так что если вы получите строку вывода из foo.Использование «| foo» вместо этого позволит вам писать в стандартный поток foo.

Вы также можете использовать open2 и open3 для одновременного выполнения обоих действий, хотя к нему применяются некоторые основные предостережения, поскольку вы можете столкнуться с неожиданными проблемами из-заIO буферизация.

2 голосов
/ 29 октября 2010

Используйте fork и exec .

0 голосов
/ 29 октября 2010

Если вам нужно получить PID Perl-скрипта, вы можете использовать переменную $$.Вы можете поместить его в ваш another_process.pl и затем вывести pid в файл.Можете ли вы быть более понятным, как вилка?Вы всегда можете использовать комбинацию fork exec.

...