Unter Linux führt das Erstellen eines Prozesses über proc_open () standardmäßig dazu, dass das PHP-Skript erst endet, wenn der erzeugte Prozess beendet wird? Ich will es nicht, und ich schließe den Prozess sofort.
proc_open selbst blockiert nicht, das ist klar genug. Aber was ist mit der allgemeinen HTTP-Anfrageausführung?
Ich hatte am Wochenende Zeit, also habe ich ein wenig über proc_open () auf * nix-Systemen recherchiert.
Während proc_open () die Skriptausführung von PHP nicht blockiert, selbst wenn das Shell-Skript nicht im Hintergrund ausgeführt wird, ruft PHP automatisch proc_close () auf, nachdem das PHP-Skript vollständig ausgeführt wurde, wenn Sie es nicht selbst aufrufen. So können wir uns vorstellen, dass wir am Ende des Skripts immer eine Zeile mit proc_close () haben.
Das Problem liegt in einem nicht offensichtlichen, aber logischen Verhalten von proc_close (). Stellen wir uns vor, wir haben ein Skript wie:
%Vor%Seltsam, proc_close () sollte warten, bevor die Ausführung des Shell-Skripts beendet wurde, aber unser Skript wurde bald beendet. Es hapert, weil wir Pipes geschlossen haben (es scheint, dass PHP es stillschweigend macht, wenn wir es vergessen), sobald das Skript versucht, etwas in eine bereits nicht existierende Pipe zu schreiben - es wird ein Fehler und endet.
Nun, lasst es uns ohne Pipes versuchen (naja, das wird es geben, aber sie werden das aktuelle tty benutzen ohne irgendeine Verbindung zu PHP):
%Vor%Nun wartet unser PHP-Skript auf das Ende unseres Shell-Skripts. Können wir es vermeiden? Glücklicherweise erzeugt PHP Shell-Skripte mit
%Vor%Also können wir einfach den sh-Prozess beenden und unser Skript laufen lassen:
%Vor%Natürlich hätten wir den Prozess einfach im Hintergrund ausführen können:
%Vor%und keine Probleme haben, aber diese Funktion führt uns zu der komplexesten Frage: Können wir einen Prozess mit proc_open () ausführen, der eine Ausgabe liest und dann den Prozess in den Hintergrund versetzt? Nun, in gewisser Weise - ja.
Das Hauptproblem hier ist Pipes: Wir können sie nicht schließen oder unser Prozess wird sterben, aber wir brauchen sie, um einige nützliche Daten aus diesem Prozess zu lesen. Es stellt sich heraus, dass wir hier einen Zaubertrick benutzen können - gdb.
Erstellen Sie zuerst eine Datei irgendwo (/ usr / share / gdb_null_descr in meinem Beispiel) mit folgendem Inhalt:
%Vor%Es wird gdb mitteilen, die Deskriptoren 1 und 2 (nun, sie sind normalerweise stdout und stderr) für neue Dateihandler zu ändern (in diesem Beispiel / dev / null, aber Sie können es ändern).
Nun, das letzte: Stellen Sie sicher, dass gdb eine Verbindung zu anderen laufenden Prozessen herstellen kann - dies ist auf einigen Systemen Standard, aber auf ubuntu 10.10 müssen Sie beispielsweise / proc / sys / kernel / yama / ptrace_scope auf 0 setzen führe es nicht als root aus.
Genießen Sie:
%Vor%edit: Ich habe vergessen zu erwähnen, dass PHP dein Shell-Skript nicht sofort ausführt, du musst also ein bisschen warten, bevor du andere Shell-Befehle ausführst, aber normalerweise ist es schnell genug (oder PHP ist langsam genug) und ich bin es zu faul, das zu meinen Beispielen hinzuzufügen.