Как мне получить PID процесса, порожденного системной функцией Perl? - PullRequest
7 голосов
/ 22 февраля 2012

Я пишу скрипт Perl (скажем, script.pl), который вызывает другой скрипт newscript.pl.Я хочу получить PID обоих сценариев только в script.pl.Я могу получить PID script.pl, используя следующий код

my $pid = Unix::PID->new();
my @p = $pid->get_pidof( $pid->get_command($$), 1 );

После этого я вызываю system для выполнения newscript.pl

system("perl newscript.pl");

Я хочу захватить сгенерированный PIDэтим newscript.pl в script.pl.

Ответы [ 2 ]

9 голосов
/ 22 февраля 2012

Номер текущего процесса находится в $$. Используйте open3 вместо system, чтобы получить номер процесса дочернего процесса.

5 голосов
/ 22 февраля 2012

Ко времени возврата system порожденный процесс уже завершится, оставив свой pid в качестве интересного исторического справочника, например, полезного для анализа журнала.

system LIST
system PROGRAM LIST

Точно так же, как exec LIST, за исключением того, что fork выполняется сначала и родительский процесс ожидаетдочерний процесс для выхода

Если вы хотите, чтобы пиды были script.pl и newscript.pl, fork и сами управляли их жизнями.С более конкретной информацией о проблеме, которую вы решаете, мы могли бы дать вам более конкретные предложения.


Чтобы блокировать другие экземпляры программы, распространенным методом является использование средства операционной системы для совместной блокировки: при запуске попытаться заблокировать определенный файл.В случае успеха ваша программа знает, что она единственная.В противном случае другой процесс уже имеет блокировку, поэтому новый процесс завершается.Ниже приведен пример.

#! /usr/bin/env perl

use strict;
use warnings;

use Fcntl qw/ :flock /;
use File::Basename;
use POSIX qw/ strftime /;

$0 = basename $0;

my $LOCK = "$ENV{HOME}/.lock-$0";

sub logmsg {
  my($msg) = @_;
  my $t = strftime "%F %T", localtime time;
  warn "$0: $t - $$ - $msg\n";
}

sub take_lock {
  open my $fh, ">", $LOCK or die "$0: open $LOCK: $!";

  unless (flock $fh, LOCK_EX | LOCK_NB) {
    logmsg "failed to lock $LOCK; exiting.";
    exit 1;
  }

  $fh;
}

my $token = take_lock;
logmsg "processing...";
sleep 2 * 60;
logmsg "done.";

Обратите внимание, что вы должны держать дескриптор файла, возвращенный из take_lock открытым, пока элемент управления находится внутри критической секции .Код выше обрабатывает его как непрозрачный токен.Когда ваша программа завершает работу, Perl закрывает дескриптор файла, который автоматически снимает блокировку.То, что вы не хотите делать, это вызывать take_lock в пустом контексте, потому что это отбросит вашу блокировку.

...