2010-12-13 10 views
2

Ich habe ein Perl-Skript, das einen anderen Prozess im Hintergrund starten und beenden muss, ohne darauf zu warten, dass das andere Skript beendet wird. Es gibt viele Threads in StackOverflow, die beschreiben, wie man in Perl wartet oder nicht auf andere Programmiersprachen wartet, aber ich kann nicht die richtige Antwort für Perl finden.Einleiten des nicht wartenden Hintergrundprozesses in Perl

Ich habe ziemlich viel gelesen und dachte, ich würde die richtigen Dinge tun, aber keiner meiner Versuche scheint richtig zu funktionieren. Hier sind alle Variationen habe ich versucht, so weit ohne Erfolg:

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 &|); 

mit jedem dieser der Eltern-Prozess weiter zu warten, bis das Kind vor dem Beenden zu beenden. Bitte lassen Sie mich wissen, was ich falsch mache und die richtige Art den Hintergrundprozess zu verändern.

Vielen Dank im Voraus für Ihre Hilfe!


Vollständiger Code zur Fehlersuche. Beachten Sie, dass die API-> Funktion() Anrufe objektorientierte Module unserer Code-Basis für bestimmte Funktionen verwendet werden, die Datenbank-Interaktionen, etc:

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

Der Elternteil wartet auf die IO in dem Kind geschlossen werden. Verwenden Sie Proc :: Daemon und den 'perldoc -q-Daemon' (oder sehen Sie sich zumindest an), um die Zuordnung von Eltern zu Kind aufzuheben. – runrig

+0

Sie werden hier irgendeine Antwort "akzeptieren"? – runrig

Antwort

4

die erste, die Art und Weise zu arbeiten ist so konzipiert - system den Befehl und Oberflächen führen damit es endet.

Die letzten beiden sind auch so konzipiert - exec ist speziell entwickelt, um nie zurückzukehren. Es ersetzt im Grunde den übergeordneten Prozess durch den untergeordneten Prozess.

Die zweite sollte jedoch den Trick machen: Der Befehl, der vom system-Aufruf gestartet wird, ist die Shell, der die auszuführende Zeichenfolge übergeben wird. Da die Zeichenfolge mit "&" endet, bedeutet das, dass die Shell Ihren Befehl als Hintergrundprozess startet und nach diesem Start ihre eigene Ausführung beendet.

Können Sie bitte mehr Code posten, der zeigt, wie # 2 nicht funktioniert hat?

auch sehen, was passiert, wenn Sie Backticks oder qx versuchen:

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

Auch als eine Möglichkeit, Unbekannten zu reduzieren, können Sie bitte die folgende und sagen Sie mir, welche Drucke laufen:

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

Lediglich der Vollständigkeit halber ist hier der etwas relevante Perlfaq-Eintrag: http://perldoc.perl.org/perlfaq8.html#How-do-I-start-a-process-in-the-background? – Hugmeir

+0

Ich glaube nicht, dass Ihr Beispiel eine nützliche Ausgabe zurückgibt. – mkb

+0

@DVK - Ich dachte, die zweite war auch korrekt, aber das Skript wartet definitiv auf den Child-Prozess zu beenden. Wenn ich die system() -Zeile auskommentiere, wird das übergeordnete Skript fast sofort beendet und mit dieser Zeile dauert es 3-4 Sekunden, um zu beenden, wie lange das Kind braucht, um es auszuführen. Ich probierte qx und ich probierte auch Backticks aus, aber keines führte das Kind überhaupt zum Laufen. Ich bin mir nicht sicher, was ich sonst noch zur Fehlerbehebung beitragen kann. Irgendwelche Ideen? –

0

Mit Gabel ist ein guter Weg, um Hintergrundprozesse:

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

Ich habe das gerade getestet und der Elternteil wartet in diesem Fall immer noch. –

+0

Das ist seltsam. Sind Sie sicher, dass Sie die Exit-Anweisung in den Child-Block geschrieben haben? – Naveed

+0

tat ich. Das Ganze ist wirklich sehr merkwürdig. Deshalb habe ich hier gepostet. Irgendwelche anderen Ideen was passieren könnte? –

3

Sie fork() nennend vor dem Anruf system oder 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 - ich verwende nicht fork(). Welcher der oben genannten Schritte ist der richtige, um einen Hintergrundprozess zu starten, auf den der Elternteil nicht wartet? Ich nehme an, dass es derjenige ist, der system() verwendet. –

+0

Sie sind beide ungefähr gleichwertig. – mkb

+0

@ mobrul/@ Matt - Beide veranlassen immer noch, dass der Elternteil wartet. Irgendwelche Ideen, wie man ändert, damit der Elternteil nicht wartet? –

3

Sie müssen das Kind vom Eltern trennen. Siehe perldoc -q-Daemon. Oder Proc::Daemon

+0

Ich möchte es nicht als Deamon ausführen. Ich möchte nur einen separaten Prozess wie nötig starten. Irgendwelche anderen Vorschläge? –

+2

@ Russell C. - Sie müssen nicht als "für immer" Daemon laufen - einfach als eine starten, Ihre Arbeit zu erledigen und zu beenden. Es gibt absolut nichts, was technisch verlangt, dass Daemon für immer läuft. +1 – DVK

Verwandte Themen