Shell Script - Zombies vermeiden

RaVenC

Mitglied
Hi :)
Ich beschäftige mich zur Zeit etwas mit der shell Programmierung unter Linux..

Sehr sehr einfaches Programm (restart_script.sh):
Code:
#!/bin/sh
php /srv/test.php

Nun beendet sich mein Programm aber nicht, da es auf das Ergebnis vom start der test.php wartet. Die test.php macht ein paar Berechnungen, welche ein paar Minuten dauern und ruft dann wieder das Miniprogramm auf, welches wieder die test.php neu startet.. also eine kleine Endlosschleife..

Das Problem ist, dass die einzelnen Prozesse sich nicht nach dem Aufruf beenden, wodurch "zombies" entstehen.

Code:
 4427 pts/1    00:00:00 restart_script.
 4428 pts/1    00:00:00 php
 4429 pts/1    00:00:00 restart_script.
 4430 pts/1    00:00:00 php
 4431 pts/1    00:00:00 restart_script.
 4432 pts/1    00:00:00 php
 4436 pts/1    00:00:00 restart_script.
 4437 pts/1    00:00:00 php
 4438 pts/1    00:00:00 restart_script.
 4439 pts/1    00:00:00 php
 4440 pts/1    00:00:00 restart_script.
 4441 pts/1    00:00:00 php
 4442 pts/1    00:00:00 restart_script.
 4443 pts/1    00:00:00 php
 4444 pts/1    00:00:00 restart_script.
 4445 pts/1    00:00:00 php
 4446 pts/1    00:00:00 restart_script.
 4447 pts/1    00:00:00 php
 4448 pts/1    00:00:00 restart_script.
 4449 pts/1    00:00:00 php
usw..

Da ich mich erst seit neustem mit der shell Programmierung beschäftige, hab ich keine Ahnung wie ich dieses Problem verhinden soll.
Google hat mir da auch leider nichts vernünftiges ausgespuckt...

Wer das Problem mal testen möchte,
im abgespeckten Format sieht die phpdatei so aus:
PHP:
<?php #!/usr/bin/php
  sleep(1);
  system("/srv/restart_script.sh");
?>

Würde mich über eine brauchbare Lösung meines Problems freuen :)

Viele Grüße
RaVenC
 
Das Problem ist dass Du hier immer wieder Kind-Prozesse erstellst und somit niemals irgendwas zu einem Ende kommen kann.

Du startest aus dem Shell-Script das PHP-Script, welches wiederum das Shell-Script startet welches dann wieder das PHP-Script startet, und so weiter...

Wenn Du mit einem Programm wie KSysGuard oder pstree schaust wirst Du sicher sehen koennen dass alles in einem Baum haengt, ausgehend vom ersten, von Dir ausgeloesten, Aufruf.

Dadurch dass Du hier einen rekursiven Aufruf hast bekommst Du eine Menge wartende Prozesse, wie Du richtig erkannt hast. Problematisch wird dies nach einer Weile da ja jeder Prozess auch etwas Speicher belegt. Irgendwann wird Dein Speicher voll sein. Das kann hier ein Weilchen dauern, bei einer solchen endlosen Rekursion ist es aber nur eine Frage der Zeit wann das geschieht.

Besser waere hier wohl die Arbeit mit einer Schleife im Shell-Script. Dadurch hast Du immer nur eine Instanz des Shell-Scripts und des PHP-Scripts. Und das PHP-Script braucht auch nicht mehr das Shell-Script aufrufen.
Und da Du jeweils nur eine Instanz hast laeuft Du auch nicht Gefahr dass irgendwann Dein Speicher volllaeuft.

Bash:
#!/bin/sh
while [ true ]; do
 php /srv/test.php
done
 
Du wirst es nicht glauben, aber ich hatte gerade im Schlaf die zündende Idee ^^

und zwar hab ich die Ausgaben umgeleitet durch das anhängen von > /dev/null &
Im restart Script steht nun:

Code:
#!/bin/sh
php /srv/test.php > /dev/null &

und in der php:
PHP:
<?php #!/usr/bin/php
  sleep(1);
  system("/srv/restart_script.sh > /dev/null & ");
?>

und siehe da:
Code:
 4457 pts/1    00:00:00 php
 4469 pts/2    00:00:00 ps

Passt das so?
Oder hab ich die Probleme damit auch nur umgeleitet?
 
Damit bekommst Du den selben endlosen Prozessbaum wie auch zuvor.
Das Problem ist ja dass der aufrufende Prozess immer darauf wartet dass sein Kind-Prozess beendet wird bevor er selbst beendet. Da der Kind-Prozess aber wiederum ein Kind erstellt, und so weiter, kann dieser Fall nie eintreten, es werden einfach immer mehr Prozesse erstellt.

Wohin die Ausgabe der Prozess geht ist belanglos.

Ob es was bringt in Deinem Fall mit & die Prozesse in den Hintergrund zu verlegen weiss ich jetzt nicht.
Das werd ich aber mal eben testen.

In jedem Fall wuerde ich aber meine Loesung vorziehen.

Edit: Okay, ich hab grad mal kurz alle 3 Loesungen (Deine beiden und meine) verglichen.
Wie schon beschrieben ist die erste vorgestellte Loesung total daneben weil es Dir halt das System total zumuellt.

Performance-technisch scheint sich zwischer Deiner 2. und meiner Loesung nicht viel zu tun, dennoch finde ich meine Loesung eleganter, und zwar aus 2. Gruenden:
  1. Der system()-Aufruf in PHP faellt weg. Ich persoenlich versuche diesen soweit moeglich zu vermeiden. Ausserdem entfaellt dadurch die Rekursion, welche ja durch die endlose while-Schleife im Shell-Script unnoetig wird.
  2. Das Konstrukt ist durch die while-Schleife leichter abbrechbar. Die Prozesse werden nicht im Hintergrund ausgefuehrt, Dein Script bleibt also im Vordergrund und ruft halt einfach nur immer wieder PHP auf. Dadurch kannst Du die gesamte Aktion mittels STRG+C abbrechen ohne noch irgendwelche Reste zu haben.
 

Neue Beiträge

Zurück