Befehl php exec (oder ähnliches), um nicht auf das Ergebnis zu warten

73

Ich habe einen Befehl, den ich ausführen möchte, aber ich möchte nicht, dass PHP sitzt und auf das Ergebnis wartet.

<?php
echo "Starting Script";
exec('run_baby_run');
echo "Thanks, Script is running in background";
?>

Ist es möglich, dass PHP nicht auf das Ergebnis wartet? Starten Sie es einfach und fahren Sie mit dem nächsten Befehl fort.

Ich kann nichts finden und bin mir nicht sicher, ob es überhaupt möglich ist. Das Beste, was ich finden konnte, war jemand, der einen CRON-Job machte, um in einer Minute zu beginnen.

greg
quelle
1
Wenn Sie dies häufig tun müssen, könnte Sie auch eine JobQueue wie Gearman interessieren .
Gordon

Antworten:

124

Aus der Dokumentation :

Um einen Befehl auszuführen und Ihr PHP-Skript während der Ausführung nicht hängen zu
lassen, darf das von Ihnen ausgeführte Programm nicht an PHP zurückgegeben werden. Leiten Sie dazu
sowohl stdout als auch stderr nach / dev / null um und geben Sie den Hintergrund ein.

> /dev/null 2>&1 &

Um einen Befehl auszuführen und
ihn als einen anderen Prozess auszulösen, der
nicht vom Apache-Thread abhängig ist
, um weiter ausgeführt zu werden (stirbt nicht, wenn
jemand die Seite abbricht), führen Sie Folgendes aus:

exec('bash -c "exec nohup setsid your_command > /dev/null 2>&1 &"');

Cristian
quelle
2
Ich danke dir sehr! Es gibt viele "Lösungen", die nicht funktionieren (Der Hauptbrowser-Thread wartet noch). Viele Lösungen geben nur das "&" am Ende an, was nicht ausreicht. Trotzdem funktionierte für mich eine einfachere Lösung: exec ('nohup your_command> / dev / null 2> & 1 &') war genug.
Vincent Pazeller
Warum müssen Sie nicht auch stdinnach / dev / null portieren ? Wird die Eingabe eines Prozesses, der mit einer Shell verknüpft ist, ausreichen, um zu verhindern, dass nohupder untergeordnete Prozess "abgelehnt" wird? (Sie ändern sich stdinin dieser Antwort: superuser.com/questions/178587/... )
NHDaly
auch, warum rufst du beide an nohupund setsid? Ich kann nicht viele Informationen darüber finden, welches besser ist oder wie sie sich unterscheiden. ( Stackoverflow.com/questions/10247721/… )
NHDaly
@Christin: Ihre Lösung funktioniert für meine Frage: stackoverflow.com/questions/25700904/… können Sie eine Antwort auf diese Frage geben ? Dann kann ich diese Frage mit einer grünen Antwort schließen.
Sugunan
@Christin: Können Sie sich bitte mein Problem ansehen, es scheint dasselbe zu sein wie mein Problem: stackoverflow.com/questions/35331958/…
Puzzled Boy
52

Sie können den Befehl im Hintergrund ausführen, indem Sie &am Ende ein hinzufügen :

exec('run_baby_run &');

Wenn Sie dies jedoch alleine tun, hängt Ihr Skript, weil:

Wenn ein Programm mit der Exec-Funktion gestartet wird, muss die Ausgabe des Programms in eine Datei oder einen anderen Ausgabestream umgeleitet werden, damit es im Hintergrund weiter ausgeführt werden kann. Andernfalls bleibt PHP hängen, bis die Ausführung des Programms beendet ist.

So können Sie die Standardausgabe des Befehls in eine Datei umleiten, wenn Sie sie später /dev/nullanzeigen möchten oder wenn Sie sie verwerfen möchten als:

exec('run_baby_run > /dev/null &');
Codaddict
quelle
1
Leitet stderr nicht um und wird von einem abstürzenden Webserver getötet.
Cees Timmerman
9

Dies verwendet wget, um eine URL über etwas zu benachrichtigen, ohne zu warten.

$command = 'wget -qO- http://test.com/data=data';
exec('nohup ' . $command . ' >> /dev/null 2>&1 & echo $!', $pid);

Dies verwendet ls, um ein Protokoll zu aktualisieren, ohne zu warten.

$command = 'ls -la > content.log';
exec('nohup ' . $command . ' >> /dev/null 2>&1 & echo $!', $pid);
Paul T.
quelle
3
Ich denke, Ihnen fehlt ein &Symbol zwischen 2>&1und echo, habe ich recht?
Santiago Aristi
2
Hält nohup das Kind auch am Laufen, wenn das Elternteil getötet wird?
Cees Timmerman
@ Santiagoarizti Ja, ich habe es behoben, da der Code nicht anders funktionierte
Mr.Web
2

Ich weiß, dass diese Frage beantwortet wurde, aber die Antworten, die ich hier gefunden habe, funktionierten nicht für mein Szenario (oder für Windows).

Ich verwende Windows 10 Laptop mit PHP 7.2 in Xampp v3.2.4.

$command = 'php Cron.php send_email "'. $id .'"';
if ( substr(php_uname(), 0, 7) == "Windows" )
{
    //windows
    pclose(popen("start /B " . $command . " 1> temp/update_log 2>&1 &", "r"));
}
else
{
    //linux
    shell_exec( $command . " > /dev/null 2>&1 &" );
}

Das hat bei mir perfekt funktioniert.

Ich hoffe es wird jemandem mit Windows helfen. Prost.

Anil
quelle
1

"exec nohup setsid your_command"

Mit nohup kann your_command fortgesetzt werden, obwohl der gestartete Prozess möglicherweise zuerst beendet wird. In diesem Fall wird das SIGNUP-Signal an Ihren Befehl gesendet, wodurch es beendet wird (es sei denn, es fängt dieses Signal ab und ignoriert es).

jobeard
quelle
Nach dieser Antwort muss sich ein Kind für SIGHUP anmelden, um über den Tod seiner Eltern informiert zu werden. Ein Terminal neigt jedoch dazu, das HUP-Signal beim Verlassen zu senden.
Cees Timmerman
1

Es gibt zwei Möglichkeiten, dies zu implementieren. Der einfachste Weg ist das direkte Ergebnis zu dev / null

exec("run_baby_run > /dev/null 2>&1 &");

Falls Sie jedoch andere Vorgänge ausführen müssen, können Sie ignore_user_abort in Betracht ziehen. In diesem Fall wird das Skript auch nach dem Schließen der Verbindung ausgeführt.

Aleksandr Ryabov
quelle