Почему процесс, который я запускаю с помощью системы Perl (), не является дочерним процессом? - PullRequest
4 голосов
/ 17 февраля 2009

Система Perl () запускает процесс, но нарушает отношения родитель / потомок?

test.pl:

use POSIX;

system("./test.sh &");

my $pid = `ps -C test.sh -o pid=`;

print "pid: -$pid-\n";

waitpid($pid, 0);

test.sh:

while true
do
    sleep 1
done

Когда я запускаю test.pl, он находит и печатает правильный pid test.sh. Но waitpid () возвращает -1 и test.pl завершается. После существования test.pl test.sh все еще работает.

Похоже, test.sh не является потомком test.pl, который ломает waitpid (). Почему это происходит и как заставить system () себя вести? Это потому, что Perl очищает детей автоматически? Если да, как я могу решить общую задачу ожидания ребенка в явном виде?

Обновление:

ответы ниже предлагают использовать fork / exec. Исходная проблема заключается в следующем:

  1. из сценария Perl, запустите утилиту командной строки, которая запускает службу. Утилита завершается, но служба остается.

  2. через некоторое время найдите pid этой службы и дождитесь его.

fork / exec не решает эту проблему, хотя и проясняет вопрос.

Ответы [ 4 ]

16 голосов
/ 17 февраля 2009

Процесс test.sh не является вашим дочерним процессом. system() разветвлял оболочку (которая является вашим дочерним элементом), эта оболочка разветвляла дочернего элемента, который запустил программу test.sh. Снаряд, из которого вышел ваш ребенок.

6 голосов
/ 17 февраля 2009

В общем, вы должны вручную выполнить fork и exec, если не хотите, чтобы Perl помогал Вы вышли Трудно точно определить, что вы делаете, но я думаю, что вы хотите это:

my $pid = fork;
unless($pid){
    # child;
    exec(qw/sh test.sh/);
}

# parent
...
waitpid $pid, 0;

Лично я предпочитаю позволить няне присматривать за детьми:

my $done = AnyEvent->condvar;

my $pid = fork;

unless( $pid ) { ... }

my $w = AnyEvent->child (
   pid => $pid,
   cb  => sub {
      my ($pid, $status) = @_;
      warn "pid $pid exited with status $status";
      $done->send;
   },
);

$done->recv; # control resumes here when child exits

Или, в более общем смысле: http://github.com/jrockway/anyevent-subprocess/tree/master

6 голосов
/ 17 февраля 2009

Что вы, вероятно, хотите сделать, это что-то вроде этого:

my $pid = fork || exec './test.sh';
print "pid: -$pid-\n";
waitpid($pid, 0);

Хотя сценарий оболочки находится в бесконечном цикле, он будет ждать вечно.

5 голосов
/ 17 февраля 2009

Для дальнейшего объяснения ответа Людвикаса -

system("./test.sh &")
 |
 |--> (P) /bin/sh (to run test.sh)
       |
       |--> (P) test.sh & (still running)

(P) - process

После разветвления и запуска сценария test.sh оболочка / bin / sh, которая была дочерним элементом системного вызова Perl, завершается, и вы получаете значение -1, возвращаемое функцией waitpid ().

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