2009-08-03 3 views
2

Wie kann ich einen Live-Zeitzähler erstellen, der parallel zum Teil eines Arbeitsprogramms auf dem Bildschirm aktiviert wird?Wie mache ich einen Zeitzähler als Kindprozess, der parallel zum Programm arbeitet?

lassen Sie uns sagen, dass ich die folgende kleine Untercode haben, das ein internes Programm für ein paar Minuten laufen:

system (`compile command`); 
exec "simu -sh"; 

Während es zu Ende warten, kann ich eine Gabel oder etwas öffnen, die Ausgabe eines laufenden stdout Uhrzeit?

Eine andere Frage kann sein, wie kann ich ausgeben, um den ALARM-Zähler zu screenen, ohne den Rest des Skripts zu verletzen?

+0

Versuchen Sie einen Fortschrittsbalken zu erstellen? –

+0

Könnte eine Option sein. – YoDar

Antwort

3

Es ist wichtig, Ihrer Frage einen Kontext zu geben. Sie haben bereits zwei Prozesse: ein Elternteil und ein Kind. Das Kind ersetzt sich selbst mit der exec, so dass Sie das Kind nicht zur Überwachung verwenden können, sondern das übergeordnete Element verfügbar ist. Wir müssen nur den waitpid Anruf non-blocking machen (d. H. Es wird nicht warten, um erfolgreich zu sein, es wird sofort fehlschlagen). Dies wird auch von der Notwendigkeit befreien für die eval und alarm Funktionen:

#!/usr/bin/perl 

use strict; 
use warnings; 
use POSIX ":sys_wait_h"; 

my $timeout = 180; 
my $program = "simulator --shell"; 

die "could not fork: $!" unless defined (my $pid = fork); 

#this is the child process 
unless ($pid) { 
    exec $program; 
    #if we reach this code the exec failed 
    die "exec of simulator failed: $!"; 
} 

#this is the parent process 
my $tries = 0; 
#check to see if $pid is done, but don't block if it isn't 
until (waitpid(-1, WNOHANG) == $pid) { 
    #put what you want to print while waiting here: 
    print scalar localtime, "\n"; 

    if ($tries++ > $timeout) { 
     warn "timed out, sending SIGKILL to simulator\n"; 
     kill 9, $pid; 
     waitpid($pid, 0); 
     last; 
    } 
} continue { 
    sleep 1; 
} 
+0

Ich habe keine Wahl oder weiß nicht über eine Möglichkeit, die Exec-Funktion zu vermeiden. Wenn ich es ausführe - der Zeitzähler kann nicht aufhören, vielleicht, weil die Exec-Funktion innerhalb des Arbeitsplatzes läuft. Gibt es noch einen Nebenweg, um den Taktzähler zu führen, während der Exec-Befehl darin ausgeführt wird? Oder kann ich den Zähler ALARM (gehört zum Befehl exec kill pid) auf den Bildschirm ausgeben? – YoDar

+0

Warum nicht einfach system() anstelle von exec() verwenden? –

+0

Ich habe die exec() als Mani in dem folgenden Link vorgeschlagen: http://stackoverflow.com/questions/1165316/how-can-i-limit-the-time-spent-in-a-specific-section- of-a-perl-script Wenn es eine andere Möglichkeit gibt, das Timeout-Fenster zu benutzen, ohne ein totes kommendes Problem zu bekommen, würde ich mich freuen, es zu wissen :) – YoDar

-1

Wie wäre es als Thread Laichen und dann warten auf einen Wert eingestellt werden (vorausgesetzt, Sie haben einen Thread aktiviert Perl):

# Modules to be used 
use strict; 
use warnings; 
# Threads module 
use Thread; 

# Share out the variable so it can be set and 
# view by main thread and spawned thread 
my $value:shared = 0; # value to be set when completed 

# Create a thread with a subroutine to compile and set the passed in reference 
# to 1 when complete. Pass in the reference to value 
my $t = Thread->new(sub {`compile command`; ${$_[0]} = 1;}, \$value); 

# Counter to count 
my $count = 0; 

# Loop until the routine set the value 
while ($value == 0) 
{ 
    # Increment the count and print it out. 
    $count++; 
    print "$count\n"; 
    # Sleep for second to let the other thread process 
    sleep 1; 
} 
# Thread as completed so join back together 
$t->join(); 

# Indicate items have completed. 
print "Done $count\n"; 

Ich führte das obige Beispiel in ActiveState PERL 5.10 unter Windows XP.

Dies gibt eine Anzeige in Sekunden, wie lange es dauerte den Befehl auszuführen. Hoffentlich suchen Sie nicht nach mehr als einer Sekunde Granularität. Sie könnten localtime() für den Zähler ersetzen, wenn Sie die tatsächliche Zeit möchten.

Ich sperre die Referenz nicht, da ich nur betroffen bin, wenn es eingestellt ist, was am Ende der Routine ist, um es abzuschließen und wieder zu verbinden.

Für weitere Informationen zu perl threads.

Oder betrachten Sie Perlmonks.

Verwandte Themen