Shell-Skripte sind beliebt, weil mit wenig Aufwand auch komplexe Aufgaben erledigt werden können. Begonnen mit den Init-Skripten bis hin zu Installationsskripten werden dabei oft Dinge erledigt, bei denen ein (unbemerktes) Fehlverhalten zu sehr schwer zu findenen Problemen führt. Eine häufige Ursache ist, dass zeitaufwändige Aufgaben zwar im Hintergrund gestartet werden, aber nicht sicher gestellt ist, dass diese auch wirklich sauber beendet werden.

Ich habe selbst vor einiger Zeit einen Fehler dieser Art finden müssen und habe dabei gelernt: Es wird schlicht vergessen, dass Kind-Prozesse ein SigHUP bekommen, wenn sich das aufrufende Skript beendet (so das Kind nicht deamonized läuft). An sich sollte dies jedem Linux/Unix-Programmierer klar sein, in scheinbar einfachen Shell-Skripten wird diese Tatsache jedoch oft vergessen oder ignoriert. Für die Problematik gibt es mehrere Lösungsansätze, die ich im Folgenden vorstellen möchte:

1. Naheliegenster Weg

Das SigHUP wird im aufgerufenen Skript abgefangen und über einen Signal-Handler entsprechend behandelt. Dies ist natürlich nur sinnvoll, wenn der Kind-Prozess überhaupt etwas ausrichten kann und die Information, dass der Kind-Prozess noch läuft nicht im aufrufenden Skript behandelt werden muss.

#! /bin/sh

trap_sighup_received() {
     echo "SigHUP received, my parent process just finished"
}

trap trap_sighup_received SIGHUP

2. Einfachster Weg

Oft ist man jedoch nur daran interessiert, das entsprechende Programm weiter laufen zu lassen. Dann kann man es von SigHUP abkoppeln, erhält jedoch wie beim ersten Weg keine Rückmeldung darüber, ob die Ausführung tatsächlich beendet wurde.

nohup /path/to/childProcess &

3. Sicherster Weg

Möchte man sicher stellen, dass eine im Hintergrund laufende Aufgabe tatsächlich auch beendet wurde, kann das aufrufende Skript auf das Ende des Kind-Prozesses warten. Dies ist zum beispiel nützlich wenn das Erstellen eines Dateisystemes im Hintergrund läuft, man den Benutzer in der Zwischenzeit beschäftigt und das Dateisystem erst einhängen möchte, wenn es auch sicher erstellt ist.

In diesem Zusammenhang sollte man sich auch angewöhnen, alle seine Kind-Prozesse am Ende des aufrufenden Skripts einzusammeln – dies gilt insbesondere, wenn das aufrufende Skript aufgrund eines Fehlers vorzeitig beendet wird.

# spawn the child process
sh /usr/bin/SohnProzess &

# save PID
pid_of_child=$!

# ..... do something different .....

# later or at the end of the script
wait $pid_of_child

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Name *

6 + vierzehn =