Signatur
Beschreibung
proc_close() beendet einen Prozess, der zuvor mit proc_open() gestartet wurde. Die Funktion wartet darauf, dass der Prozess vollständig beendet ist, und gibt anschließend seinen Exitcode zurück. Vor dem Aufruf sollten alle mit dem Prozess verbundenen Pipes (Datei-Handles) geschlossen werden, da es sonst zu einem Deadlock kommen kann – insbesondere wenn der Kindprozess auf das Schreiben in eine Pipe wartet, die noch nicht gelesen wurde.
Der zurückgegebene Exitcode entspricht dem Rückgabewert des gestarteten Prozesses: 0 steht üblicherweise für Erfolg, jeder andere Wert für einen Fehler. Auf Unix-Systemen wird der Exitcode über waitpid() ermittelt.
Diese Funktion ist essenziell für das saubere Ressourcen-Management, wenn externe Programme über proc_open() aufgerufen werden. Wird sie nicht aufgerufen, können Zombie-Prozesse entstehen oder Ressourcen belegt bleiben. Der Aufruf ist daher immer am Ende eines proc_open()-Blocks empfehlenswert, idealerweise in einem finally-Block.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $process Pflicht | resource | Die Prozess-Ressource, die von proc_open() zurückgegeben wurde. |
Rückgabewert
0 bedeutet üblicherweise Erfolg. Gibt -1 zurück, wenn der Exitcode nicht ermittelt werden konnte oder der übergebene Parameter keine gültige Prozess-Ressource ist.Beispiele
Einfaches Beispiel: Externen Befehl ausführen und Exitcode auslesen
<?php
$descriptorspec = [
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w'], // stderr
];
$process = proc_open('ls -la /tmp', $descriptorspec, $pipes);
if (is_resource($process)) {
// Ausgabe lesen
$output = stream_get_contents($pipes[1]);
$errors = stream_get_contents($pipes[2]);
// Pipes ZUERST schließen, um Deadlocks zu vermeiden
fclose($pipes[0]);
fclose($pipes[1]);
fclose($pipes[2]);
// Prozess schließen und Exitcode ermitteln
$exitCode = proc_close($process);
echo "Ausgabe:\n" . $output;
echo "Fehler:\n" . $errors;
echo "Exitcode: " . $exitCode . "\n";
}
Robuste Verwendung mit finally-Block
<?php
$descriptorspec = [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
];
$process = proc_open('php -r "exit(42);"', $descriptorspec, $pipes);
if (!is_resource($process)) {
throw new RuntimeException('Prozess konnte nicht gestartet werden.');
}
try {
$stdout = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
} finally {
// Sicherstellen, dass Pipes und Prozess immer geschlossen werden
foreach ($pipes as $pipe) {
if (is_resource($pipe)) {
fclose($pipe);
}
}
$exitCode = proc_close($process);
}
echo "Exitcode: " . $exitCode . "\n"; // Erwartet: 42
// Wichtig · Fallstricke
Deadlock-Gefahr: Werden die Pipes nicht vor dem Aufruf von proc_close() geschlossen, kann ein Deadlock entstehen. Dies passiert, wenn der Kindprozess blockiert, weil er in eine volle Pipe schreiben möchte, während der Elternprozess in proc_close() auf das Ende des Kindprozesses wartet. Schließe daher immer zuerst alle Pipes, bevor du proc_close() aufrufst.
Sicherheitshinweis: Beim Übergeben von Benutzereingaben an proc_open() ist unbedingt escapeshellarg() oder escapeshellcmd() zu verwenden, um Shell-Injection zu verhindern. proc_close() selbst ist davon nicht betroffen.
Auf Windows-Systemen kann der Exitcode von dem auf Unix-Systemen abweichen. Das Verhalten bei Signals (z. B. SIGKILL) kann ebenfalls plattformabhängig sein.