PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PID von child-Prozess in Perl



RAHUL
09-06-2006, 15:24
Hallo,

ich möchte die Argumente meines Perl-Progrämmchen in einer Schleife durchlaufen lassen.
In der Schleife werden die Argumente einzeln an eine Applikation übergeben,
die Applikation nach 5 Sekunden gekillt und das nächste Argument aufgerufen.

Um die Applikation zu killen, brauche ich aber die PID des jeweiligen Applikations-Aufrufs,
ich habe aber keine Ahnung wie ich die am elegantesten herbeizaubere.

Ich würde die Applikation lieber über system laufen lassen,
nun habe ich im Netz gelesen, dass einer die PID über "grep ps" holt,
finde ich aber, nach ein wenig experimentieren, nicht so schön.

Dann gibt es auch noch fork, da habe ich mich aber irgendwie nicht
herangewagt, weil es auch irgendwie "schmutzig" aussieht.

Wie seht ihr Profis das, was ist für einen Anfänger der beste Weg,
sich die PID zu holen?

Mfg
Rahul

RAHUL
12-06-2006, 15:22
Hallo,

ich habe mich jetzt für die grep ps Variante entschieden,
aber das Testen der Zeit habe ich an die dabei modifzierte
Output-Datei gekoppelt.
Dabei tritt hängt das Programm sich in der letzten Schleife auf,
was mir aber nicht einleuchtet, denn den Prozess killt er schon
(sieht zumindest so aus!, vllt kenn ich die shell aber auch zu schlecht),
wie kommt der Interpreter also zu der letzten Zeile, aber bleibt trotzdem in
der while-Schleife hängen...

Hier ist der Code:


1 #! /usr/bin/perl -w
2 use strict;
3
4 #Test of Argument Invocation
5 warn "Alle weiteren Argumente außer dem ersten werden vernachlässigt!\n" if(@ARGV!=1);
6 defined ($ARGV[0]) or die "Falsche Eingabe: Keine Argumente!\n";
7
8 #Global Vars
9 my ($mt1, $mt2)=(0,0);
10 my $timeMin=10;
11 my $psCrystal;
12 (my $output_name=$ARGV[0]) =~ s/\.d12\b/.op/;
13 my $PID=undef;
14
15 #Call Process "crystal"
16 system "crystal < $ARGV[0] > $output_name &";
17 $mt1=(stat $output_name)[9] until ($mt1);#Starttime-Marker
18 print "\$mt1 = $mt1\n";
19
20 #grep PID: Crystal-Process
21 open (LIST, "ps -e|grep 'crystal'|") or die "Fehler beim Ausführen von \"ps -e\": $!!";
22 while (<LIST>){
23 m/\s+\d+:\d{2}:(\d{2})\s+/;
24 if ($1 < $timeMin){
25 $timeMin=$1;
26 $psCrystal=$_;
27 }
28 }
29 $psCrystal=~ m/^\s*(\d{1,5})\s./;
30 $PID=$1;
31 print "PID = $PID\n";
32
33 #kill Process after 5secs
34 while(($mt2-$mt1) < 10){ # Hier bleibt er hängen und $mt2 wird ständig ausgegeben
35 print "\$mt2 = $mt2\n";
36 $mt2=(stat $output_name)[9];
37 }
38 kill 2, $PID and "Prozess $PID gekillt\n" or warn "PID $PID ist nicht vorhanden, kann nicht killen, bitte per Hand killen!\n";


Danke für die Antworten...
MfG
Rahul

Romanday
12-06-2006, 18:10
Hallo,
wie kommt der Interpreter also zu der letzten Zeile, aber bleibt trotzdem in
der while-Schleife hängen...
Danke für die Antworten...
MfG
Rahul

Ich habe es auch noch nicht probiert, aber ...
Die Shell hat genau umgekehrte TRUE/FALSE Werte wie Perl.
Daher würde ich so etwas nicht unbedingt mit system() regeln.

Vielleicht hilft dir:
http://de.selfhtml.org/perl/funktionen/systemaufrufe.htm
http://www.linuxfibel.de/proccontrol.htm

weiter.

Um Komplikationen zu vermeiden, ist es bestimmt einfacher
sich für ein auschließliches Shell- oder Perlscript zu entscheiden.

Und dann arbeite mal ein wenig mehr mit sleep. Dann kannst du
besser den Ablauf kontrolieren und leichter Fehler finden.

michael.sprick
12-06-2006, 19:01
system() wartet auf die Beendigung des aufgerufenen Prozesses. Als beendet sieht system() einen Prozess dann an, wenn der Exit-Status zurückgegeben wird. Das "&" im Aufruf nützt Dir also nix ;)

Bei Deinem Skript wird das Programm 'crystal' ausgeführt und NACH Beendigung der Rest - will heißen:

a) die Variablen $mt1 und $mt2 sind und bleiben immer gleich. Dadurch ergibt $mt2 - $mt1 immer 0, was wiederum < 10 ist... -> Endlosschleife ab Zeile 34

b) Du bekommst die Prozess ID nicht in Zeile 21 - Falls Du da doch eine Prozess ID bekommst, ist es die, des grep 'crystal' Befehls ODER sogar die eines anderen crystal Prozesses. Auf garkeinen Fall allerdings erhälst Du die PID des zuvor per system() gestarteten Programms.

c) das kill() ist natürlich auch unwirksam - keine PID, kein kill ;)

Such mal nach Threads in diesem Zusammenhang, das sollte Dir helfen...

RAHUL
13-06-2006, 09:55
Hallo und Danke für die Antworten,

@Romanday
sleep war ein guter Tipp, auch die Links waren hilfreich

@Michael Sprick: danke für die Erläuterungen, heißt Teil b.) eigentlich,
daß es sich doch eher anbieten würde mit fork() zu arbeiten, selbst wenn ich sleep verwende...

Edit: was ich allerdings nicht raffe, ist, wenn mit "system" erst der child-Prozess ausgeführt wird und Perl auf das Prozessende wartet,
wieso bleibt das Programm in der while-schleife hängen (sehe ich ja an der Ausgabe von $mt2)
So ein crystal Programm dauert normalerweise Stunden, manchmal Tage und so lange habe ich noch nicht abgewartet ;).

MfG
Rahul