Signatur
Beschreibung
pcntl_exec() führt das unter $path angegebene Programm im aktuellen Prozessraum aus, indem es den POSIX-Syscall execve(2) aufruft. Das bedeutet: Sobald der Aufruf erfolgreich ist, wird der PHP-Prozess vollständig durch das neue Programm ersetzt. PHP-Code nach dem Aufruf wird nie mehr ausgeführt.
Die Funktion ist eng verwandt mit dem klassischen Unix-Pattern fork-exec: Man erzeugt mit pcntl_fork() einen Kind-Prozess und ruft in diesem pcntl_exec() auf, um ein externes Binary zu starten, während der Eltern-Prozess weiterläuft. Dieses Muster wird etwa zum Starten von Sub-Prozessen, Daemon-Prozessen oder zur Prozesskettensteuerung eingesetzt.
Optionale Argumente werden als numerisches Array $args übergeben und entsprechen argv[1], argv[2], … des Zielprogramms. Über $env_vars lassen sich Umgebungsvariablen als assoziatives Array ('VARIABLE' => 'Wert') definieren; wird das Array weggelassen, erbt der neue Prozess die aktuelle Umgebung.
Die Funktion steht nur auf POSIX-kompatiblen Systemen (Linux, macOS, BSD) zur Verfügung und erfordert die Kompilierung von PHP mit --enable-pcntl. Sie ist nicht für den Einsatz in Web-SAPIs (Apache, FPM) geeignet, sondern ausschließlich für CLI-Skripte.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $path Pflicht | string | Absoluter Dateipfad zum auszuführenden Binary oder Skript (z. B. /usr/bin/python3). Der Pfad muss ausführbar sein. |
|
| $args | array | [] | Numerisches Array der Kommandozeilen-Argumente, die dem Programm als argv[1], argv[2], … übergeben werden. argv[0] (Programmname) wird automatisch auf $path gesetzt. |
| $env_vars | array | [] | Assoziatives Array der Umgebungsvariablen in der Form ['NAME' => 'Wert']. Wird ein leeres Array übergeben, erhält der neue Prozess eine leere Umgebung. Wird der Parameter ganz weggelassen, wird die aktuelle Umgebung vererbt. |
Rückgabewert
false zurück, wenn das Programm nicht gestartet werden konnte (z. B. Datei nicht gefunden, keine Ausführrechte). Bei Erfolg kehrt die Funktion nicht zurück, da der Prozess ersetzt wurde.Beispiele
Aktuellen Prozess durch ls ersetzen
<?php
// Einfachstes Beispiel: PHP-Prozess wird durch /bin/ls ersetzt.
// Alles danach wird NICHT ausgeführt.
$result = pcntl_exec('/bin/ls', ['-la', '/tmp']);
// Hierher kommt man nur, wenn exec fehlgeschlagen ist:
if ($result === false) {
echo 'Fehler: ' . posix_strerror(posix_get_last_error()) . PHP_EOL;
}
fork-exec-Pattern: Kind-Prozess startet externes Programm
<?php
// Typisches Unix-Pattern: fork, dann exec im Kind-Prozess.
$pid = pcntl_fork();
if ($pid === -1) {
exit('fork() fehlgeschlagen');
}
if ($pid === 0) {
// Kind-Prozess: ersetzt sich selbst durch curl
pcntl_exec('/usr/bin/curl', [
'--silent',
'--output', '/tmp/result.html',
'https://example.com'
]);
// Nur erreichbar bei Fehler:
exit(1);
}
// Eltern-Prozess wartet auf den Kind-Prozess
pcntl_waitpid($pid, $status);
if (pcntl_wifexited($status)) {
$code = pcntl_wexitstatus($status);
echo "curl beendet mit Exit-Code: {$code}" . PHP_EOL;
}
Umgebungsvariablen explizit setzen
<?php
// Programm mit einer definierten, minimalen Umgebung starten.
pcntl_exec(
'/usr/bin/env',
[],
[
'PATH' => '/usr/local/bin:/usr/bin:/bin',
'HOME' => '/tmp',
'LANG' => 'de_DE.UTF-8',
]
);
// Ausgabe (falls exec erfolgreich): die drei Umgebungsvariablen
// Wichtig · Fallstricke
Sicherheit: Nutzer-Eingaben dürfen niemals ungefiltert als $path oder in $args übergeben werden. Auch wenn pcntl_exec() keine Shell verwendet (im Gegensatz zu shell_exec()), sind Path-Traversal-Angriffe (../../bin/sh) möglich. Pfade immer validieren und auf eine Allowlist beschränken.
Kein Rücksprung bei Erfolg: Das Programm ersetzt den Prozess vollständig. register_shutdown_function()-Callbacks, Destruktoren und finally-Blöcke werden nicht ausgeführt. Ressourcen (Datenbankverbindungen, Dateisperren) sollten vor dem Aufruf explizit freigegeben werden.
Nur CLI: Die PCNTL-Extension ist explizit für CLI-Skripte konzipiert. Der Einsatz unter Web-SAPIs (Apache mod_php, FPM) kann zu schwer vorhersehbarem Verhalten führen und sollte vermieden werden.
argv[0]: Das neue Programm sieht als argv[0] den Wert von $path. Es gibt keine Möglichkeit, argv[0] separat zu überschreiben.