Problem
Ich habe ein Formular, das bei der Übermittlung Basiscode ausführt, um die übermittelten Informationen zu verarbeiten und in eine Datenbank einzufügen, um sie auf einer Benachrichtigungswebsite anzuzeigen. Außerdem habe ich eine Liste von Personen, die sich angemeldet haben, um diese Benachrichtigungen per E-Mail und SMS zu erhalten. Diese Liste ist im Moment trivial (nur etwa 150), es reicht jedoch aus, um zu veranlassen, dass es mehr als eine Minute dauert, um die gesamte Abonnententabelle zu durchlaufen und mehr als 150 E-Mails zu versenden. (Die E-Mails werden aufgrund von Massen-E-Mail-Richtlinien einzeln gesendet, wie von den Systemadministratoren unseres E-Mail-Servers angefordert.)
Während dieser Zeit bleibt die Person, die die Warnung veröffentlicht hat, fast eine Minute lang auf der letzten Seite des Formulars, ohne dass positiv bestätigt wird, dass ihre Benachrichtigung veröffentlicht wird. Dies führt zu anderen potenziellen Problemen, die alle mögliche Lösungen haben, die ich für weniger als ideal halte.
Erstens könnte das Poster glauben, dass der Server hinterherhinkt, und erneut auf die Schaltfläche "Senden" klicken, wodurch das Skript neu gestartet oder zweimal ausgeführt wird. Ich könnte dies lösen, indem ich JavaScript verwende, um die Schaltfläche zu deaktivieren und den Text zu ersetzen, um so etwas wie "Verarbeitung ..." zu sagen. Dies ist jedoch nicht ideal, da der Benutzer für die Dauer der Skriptausführung immer noch auf der Seite hängen bleibt. (Wenn JavaScript deaktiviert ist, besteht dieses Problem weiterhin.)
Zweitens schließt das Poster möglicherweise die Registerkarte oder den Browser vorzeitig, nachdem das Formular gesendet wurde. Das Skript wird auf dem Server so lange ausgeführt, bis es versucht, in den Browser zurückzuschreiben. Wenn der Benutzer dann jedoch zu einer beliebigen Seite in unserer Domäne navigiert (während das Skript noch ausgeführt wird), bleibt der Browser beim Laden der Seite hängen, bis das Skript beendet ist . (Dies geschieht nur, wenn eine Registerkarte oder ein Fenster des Browsers geschlossen ist und nicht die gesamte Browseranwendung.) Dies ist jedoch nicht ideal.
(Möglich) Lösung
Ich habe beschlossen, den "E-Mail" -Teil des Skripts in eine separate Datei aufzuteilen, die ich nach dem Posten der Benachrichtigung aufrufen kann. Ich dachte ursprünglich daran, dies auf die Bestätigungsseite zu setzen, nachdem die Benachrichtigung erfolgreich veröffentlicht wurde. Der Benutzer weiß jedoch nicht, dass dieses Skript ausgeführt wird, und Anomalien sind für ihn nicht erkennbar. Dieses Skript kann nicht fehlschlagen.
Aber was ist, wenn ich dieses Skript als Hintergrundprozess ausführen kann? Meine Frage lautet also: Wie kann ich ein PHP-Skript ausführen, um es als Hintergrunddienst auszulösen und völlig unabhängig davon auszuführen, was der Benutzer auf Formularebene getan hat?
EDIT: Dies kann nicht gekrönt werden. Es muss sofort ausgeführt werden, wenn das Formular gesendet wird. Dies sind Benachrichtigungen mit hoher Priorität. Darüber hinaus verbieten die Systemadministratoren, auf denen unsere Server ausgeführt werden, dass Cron häufiger als 5 Minuten ausgeführt wird.
quelle
exec()
aber ich habe das nie versucht.ajax
und füge einfachsleep()
mit Zeitintervall in die Schleife ein (in meinem Fall foreach), um den Hintergrundprozess auszuführen. Es funktioniert perfekt in meinem Server. Ich bin mir nicht sicher über die anderen. Ich füge außerdemignore_user_abort()
undset_time_limit()
(mit berechneter Endzeit) vor der Schleife hinzu, um sicherzustellen, dass das Skript nicht von dem Server gestoppt wird, den ich verwende, auch nach meinem Test, wenn das Skript die Aufgabe ohneignore_user_abort()
und ausführtset_time_limit()
.gearman
mit PHP, um Hintergrundaufgaben zu erledigen. Es ist perfekt zu skalieren, wenn Sie auf große Zeitverarbeitung und hohe Lasten stoßen. Sie sollten einen Blick darauf werfen.Antworten:
Doing einige Experimente mit
exec
undshell_exec
ich habe eine Lösung entdeckt , die perfekt funktioniert! Ich entscheide mich für die Verwendung,shell_exec
damit ich jeden Benachrichtigungsprozess protokollieren kann, der stattfindet (oder nicht). (shell_exec
Gibt als Zeichenfolge zurück und dies war einfacher als die Verwendungexec
, die Ausgabe einer Variablen zuzuweisen und dann eine Datei zum Schreiben zu öffnen.)Ich verwende die folgende Zeile, um das E-Mail-Skript aufzurufen:
Es ist wichtig, das
&
am Ende des Befehls zu beachten (wie von @netcoder hervorgehoben). Dieser UNIX-Befehl führt einen Prozess im Hintergrund aus.Die zusätzlichen Variablen in einfachen Anführungszeichen nach dem Pfad zum Skript werden als
$_SERVER['argv']
Variablen festgelegt, die ich in meinem Skript aufrufen kann.Das E-Mail-Skript gibt dann mithilfe von Folgendes in meine Protokolldatei aus
>>
und gibt Folgendes aus:quelle
$post_id
nach dem Pfad des PHP-Skripts?$post_id
. Ich würde es lieber direkt auf eine Zahl übertragen :(int) $post_id
. (Auf Linux / Unix-Servern können Sie einen Job im Hintergrund mit proc_open ausführen :
Das
&
Sein ist hier das Wichtigste. Das Skript wird auch dann fortgesetzt, wenn das ursprüngliche Skript beendet wurde.quelle
proc_close
wenn die Aufgabe abgeschlossen ist.proc_close
Lässt das Skript etwa 15 bis 25 Sekunden hängen. Ich müsste ein Protokoll mit den Pipe-Informationen führen, also muss ich eine Datei öffnen, in die geschrieben werden soll, sie schließen und dann die Proc-Verbindung schließen. Leider funktioniert diese Lösung bei mir nicht.proc_close
, das ist der Punkt! Und ja, Sie können mit zu einer Datei leitenproc_open
. Siehe aktualisierte Antwort.Von allen Antworten berücksichtigte keine die lächerlich einfache Funktion fastcgi_finish_request , die beim Aufruf alle verbleibenden Ausgaben in den Browser löscht und die Fastcgi-Sitzung und die HTTP-Verbindung schließt, während das Skript im Hintergrund ausgeführt wird.
Ein Beispiel:
quelle
PHP
exec("php script.php")
kann es schaffen.Aus dem Handbuch :
Wenn Sie also die Ausgabe in eine Protokolldatei umleiten (was sowieso eine gute Idee ist), bleibt Ihr aufrufendes Skript nicht hängen und Ihr E-Mail-Skript wird in bg ausgeführt.
quelle
Und warum nicht eine HTTP-Anfrage für das Skript stellen und die Antwort ignorieren?
http://php.net/manual/en/function.httprequest-send.php
Wenn Sie Ihre Anfrage für das Skript stellen, das Sie aufrufen müssen, wird Ihr Webserver im Hintergrund ausgeführt, und Sie können (in Ihrem Hauptskript) eine Meldung anzeigen, die dem Benutzer mitteilt, dass das Skript ausgeführt wird.
quelle
Wie wäre es damit?
Dieses zweite PHP-Skript sollte so eingestellt sein, dass es als Cron ausgeführt wird.
quelle
Wie ich weiß, können Sie dies nicht auf einfache Weise tun (siehe Fork Exec usw. (funktioniert nicht unter Windows)). Möglicherweise können Sie den Ansatz umkehren und den Hintergrund des Browsers verwenden, der das Formular in Ajax veröffentlicht Arbeit hast du keine Wartezeit.
Dies kann auch dann hilfreich sein, wenn Sie einige lange Ausarbeitungen vornehmen müssen.
Beim Senden von E-Mails wird immer empfohlen, einen Spooler zu verwenden. Möglicherweise handelt es sich um einen lokalen und schnellen SMTP-Server, der Ihre Anforderungen akzeptiert und diese an den echten MTA weiterleitet oder alle in eine Datenbank stellt, als einen Cron, der die Warteschlange spoolt.
Der Cron befindet sich möglicherweise auf einem anderen Computer, der den Spooler als externe URL aufruft:
quelle
Hintergrund Cron Job klingt nach einer guten Idee dafür.
Sie benötigen SSH-Zugriff auf den Computer, um das Skript als Cron auszuführen.
$ php scriptname.php
um es auszuführen.quelle
Wenn Sie über ssh auf den Server zugreifen und Ihre eigenen Skripte ausführen können, können Sie mit PHP einen einfachen FIFO-Server erstellen (obwohl Sie PHP mit
posix
Unterstützung für neu kompilieren müssenfork
).Der Server kann wirklich in alles geschrieben werden, Sie können es wahrscheinlich leicht in Python tun.
Oder die einfachste Lösung wäre, eine HttpRequest zu senden und die Rückgabedaten nicht zu lesen, aber der Server könnte das Skript zerstören, bevor die Verarbeitung abgeschlossen ist.
Beispielserver:
Beispielclient:
quelle
Die einfachere Möglichkeit, ein PHP-Skript im Hintergrund auszuführen, ist
Das Skript wird im Hintergrund ausgeführt und die Seite erreicht die Aktionsseite auch schneller.
quelle
Angenommen, Sie laufen auf einer * nix-Plattform, verwenden Sie
cron
und diephp
ausführbare Datei.BEARBEITEN:
Es gibt bereits eine ganze Reihe von Fragen zu "PHP ohne Cron ausführen" auf SO. Hier ist eine:
Planen Sie Skripte ohne CRON
Trotzdem klingt die Antwort von exec () oben sehr vielversprechend :)
quelle
Wenn Sie unter Windows arbeiten, recherchieren Sie
proc_open
oderpopen
...Wenn wir uns jedoch auf demselben Server "Linux" befinden, auf dem cpanel ausgeführt wird, ist dies der richtige Ansatz:
Verwenden Sie es nicht
fork()
odercurl
wenn Sie Zweifel haben, dass Sie damit umgehen können, ist es wie der Missbrauch Ihres ServersSchließlich auf der
script.php
Datei , die oben genannt wird, zur Kenntnis nehmen diese stellen Sie sicher , Sie schreibt:quelle
Für Hintergrundarbeiter denke ich, dass Sie diese Technik ausprobieren sollten. Es wird hilfreich sein, so viele Seiten aufzurufen, wie Sie möchten. Alle Seiten werden unabhängig voneinander gleichzeitig ausgeführt, ohne auf jede Seitenantwort als asynchron zu warten.
form_action_page.php
testpage.php
PS: Wenn Sie URL-Parameter als Schleife senden möchten, folgen Sie dieser Antwort: https://stackoverflow.com/a/41225209/6295712
quelle
In meinem Fall habe ich 3 Parameter, einer davon ist string (mensaje):
In meiner Process.php habe ich diesen Code:
quelle
Das funktioniert bei mir. Tyr dies
quelle
serialize()
Funktion. Ich habe zum Beispiel einindex.php
Formular und sende einen Wert über Ajax an index2.php. Ich möchte das Senden von Daten in index2.php im Hintergrund durchführen. Was schlagen Sie vor? dankeVerwenden Sie Amphp , um Jobs parallel und asynchron auszuführen.
Installieren Sie die Bibliothek
Codebeispiel
Für Ihren Anwendungsfall können Sie Folgendes tun
quelle