2010-12-13 1 views
2

У меня есть сценарий Perl, который должен запустить другой процесс в фоновом режиме и выйти, не дожидаясь завершения другого скрипта. Есть много потоков на StackOverflow, которые покрывают, как ждать на Perl или как не ждать других языков программирования, но я не могу найти правильный ответ для Perl.Инициирование неосведомленного фонового процесса в Perl

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

system(qq|perl /util/script.pl $id|); 

system(qq|perl /util/script.pl $id &|); 

exec(qq|perl /util/script.pl $id|); 

exec(qq|perl /util/script.pl $id &|); 

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

Заранее благодарим за вашу помощь!


Полный код, который поможет при отладке. Обратите внимание, что API-> Function() вызовы объектно-ориентированные модули наш базовый код использует для конкретных функций, взаимодействия баз данных и т.д.:

sub Add { 
    my $self = shift; 
    my $domain = shift; 

    if(!$self->IsValid($domain)) { return; } 

    my $SQL = qq| insert into domains set added=NOW(),domain=| . API->Database->Quote($domain); 
    my $sth = API->DatabaseQuery($SQL); 

    $SQL = qq| select last_insert_id() |; 
    $sth = API->DatabaseQuery($SQL); 
    my $id = $sth->fetchrow_array(); 

    my $command = qq|perl /home/siteuser/util/new.pl $id &|; 
    system($command); 

    return {'id'=>$id,'domain'=>$domain}; 
} 
+0

Родитель ожидает, когда IO в ребёнке будет закрыт. Используйте (или, по крайней мере, посмотрите) Proc :: Daemon и «perldoc -q daemon» о том, как отделить родителя от дочернего. – runrig

+0

Вы собираетесь «принять» любой ответ здесь? – runrig

ответ

4

Первый предназначен для работы таким образом - system выполняет команду и отделок для того, чтобы это закончилось.

Последние два также спроектированы таким образом - exec специально разработан, чтобы никогда не возвращаться. Он в основном заменяет родительский процесс дочерним процессом.

Однако второй должен сделать трюк: команда, запущенная из вызова system, является оболочкой, которой дана ваша строка для выполнения. Поскольку строка заканчивается на «&», это означает, что оболочка запустит вашу команду в качестве фонового процесса и завершит свое собственное выполнение после этого запуска.

Можете ли вы отправить больше кода, иллюстрирующего, как № 2 не работает?

Кроме того, посмотрим, что произойдет, если вы попытаетесь кавычку или QX:

my $output = qx|perl /util/script.pl $id &|; 
print $output; 

Кроме того, в качестве способа снижения неизвестных, пожалуйста, вы можете выполнить следующую команду и скажите, что печатает:

my $output = qx|(echo "AAAAAAA"; /bin/date; sleep 5; /bin/date; echo "BBBBBBB") &|; 
print $output; 
+0

Просто для полноты, вот несколько важная запись perlfaq: http://perldoc.perl.org/perlfaq8.html#How-do-I-start-a-process-in-the-background? – Hugmeir

+0

Я не думаю, что ваш пример вернет любой полезный результат. – mkb

+0

@DVK - Я думал, что второй был правильным, но сценарий определенно ждет завершения дочернего процесса. Если я прокомментирую строку system(), то родительский скрипт выйдет почти сразу, и с этой строкой требуется 3-4 секунды, чтобы выйти, сколько времени занимает ребенок для выполнения. Я пробовал qx, и я также пытался использовать backticks, но ни один из них не запускал ребенка вообще. Я не уверен, что еще я могу предоставить, чтобы помочь в устранении неполадок. Есть идеи? –

0

Использование вилки является хорошим способом для фоновых процессов:

my $pid = fork; 
die "fork failed" unless defined $pid; 
if ($pid == 0) { 
    # child process goes here 
    do '/util/script.pl'; 
    exit; 
} 
# parent process continues here 
+0

Я просто проверил это, и родитель все еще ждет в этом случае. –

+0

Это странно. Вы уверены, что поставили оператор exit внутри дочернего блока? – Naveed

+0

я сделал. Все это очень странно. Вот почему я разместил здесь. Любые другие идеи, что может произойти? –

3

вы звоните fork() перед вызовом system или exec?

my $pid = fork(); 
if (defined($pid) && $pid==0) { 
    # background process 
    my $exit_code = system($command); 
    exit $exit_code >> 8; 
} 


my $pid = fork(); 
if (defined($pid) && $pid==0) { 
    # background process 
    exec($command); 
    # doesn't^H^H^H^H^H^H shouldn't return 
} 
+0

@mobrule - я не использую fork(). Какое из вышеперечисленных является правильным, чтобы начать фоновый процесс, который родитель не ждет? Я предполагаю, что это тот, который использует system(). –

+0

Они оба примерно эквивалентны. – mkb

+0

@ mobrul/@ Matt - Оба по-прежнему заставляют родителя ждать. Любые идеи о том, как модифицировать, чтобы родитель не дождался? –

3

Необходимо отделить ребенка от родителя. См. Perldoc -q daemon. Или Proc::Daemon

+0

Я не хочу запускать его как деамон. Я просто хочу, чтобы это произошло, - это отдельный процесс по мере необходимости. Любые другие предложения? –

+2

@ Russell C. - вам не нужно запускать как «вечно» демон - просто начинайте как один, выполняйте свою работу и выходите. Нет абсолютно ничего, что технически требовало бы, чтобы демон работал вечно. +1 – DVK

 Смежные вопросы

  • Нет связанных вопросов^_^