Frage

Ich versuche, ein PHP-Skript zu machen, ich habe das Skript fertig, aber es dauert wie 10 Minuten, den Prozess zu beenden, es konzipiert ist zu tun. Dies ist kein Problem, aber ich nehme an ich habe die Seite zu halten, die ganze Zeit geladen, die lästig ist. Kann ich es habe, so dass ich den Prozess und dann wieder 10 Minuten später beginnen und nur die Protokolldatei anzuzeigen es erzeugt hat?

War es hilfreich?

Lösung

Nun, können Sie „ ignore_user_abort ( true) "

So das Skript wird auch weiterhin ein Auge auf Skript Dauer arbeiten (halten, vielleicht hinzufügen „ set_time_limit (0) ")

Aber eine Warnung hier: Sie werden nicht in der Lage sein, ein Skript mit diesen beiden Linien zu stoppen:

ignore_user_abort(true); 
set_time_limit(0);

Mit Ausnahme Sie können direkt auf den Server zugreifen und den Prozess dort töten! (Da, eine Endlosschleife, die sich selbst immer und immer wieder hat der Server zu einem Kreischen zum Stillstand gekommen, rief bekam bei ...)

Andere Tipps

Klingt wie Sie eine Warteschlange und ein externes Skript für die Verarbeitung der Warteschlange haben sollten.

Zum Beispiel PHP-Skript sollte einen Eintrag in eine Datenbank-Tabelle setzen und sofort zurück. Dann wird ein cron jede Minute laufen überprüft die Warteschlange und Gabeln ein Prozess für jeden Job.

hier der Vorteil, dass Sie nicht ein Apache-gewinde für 10 Minuten sperren.

Ich hatte viele Probleme mit dieser Art von Prozess unter Windows; Meine Situation war ein wenig anders, dass ich nicht über die Antwort des „script“ scherte - ich das Drehbuch wollte andere Seite Anfragen zu starten und durchlassen, während er damit beschäftigt war, Arbeit weg

.

Aus irgendeinem Grund; Ich hatte Probleme mit ihm entweder anderen Anfragen oder Ablaufen nach etwa 60 Sekunden hängen (beide Apache und PHP nach etwa 20 Minuten zu Zeit eingestellt wurden); Es stellt sich auch heraus, dass firefox mal aus nach 5 Minuten (Standard) ohnehin so nach diesem Punkt kann man nicht wissen, was über den Browser vor sich geht, ohne die Einstellungen in Firefox zu ändern.

ich am Ende mit dem Prozess offen und Verfahren schließen Methoden wie so einen PHP in cli-Modus zu öffnen:

pclose(popen("start php myscript.php", "r"));

Dies würde (mit Start) öffnen Sie den PHP-Prozess und dann den Startvorgang für wie lange laufen lassen PHP töten sie benötigt - wieder würden Sie den Prozess beenden müssen manuell herunterzufahren. Es dauerte nicht benötigen Sie keine Auszeiten zu setzen und Sie können die aktuelle Seite lassen, dass es weiter und Ausgabe einige weitere Details genannt.

Das einzige Problem dabei ist, dass wenn Sie das Skript alle Daten zu senden, können Sie es entweder über eine andere Quelle tun würde oder es entlang der „Befehlszeile“ als Parameter übergeben; das ist nicht so sicher.

Arbeitete gut für das, was wir brauchten, obwohl und sorgt für das Skript immer beginnt und erlaubt ohne Unterbrechungen zu laufen.

Dies kann hilfreich sein, auch: Asynchronous Shell exec in PHP

Sie könnten ignore_user_abort() - auf diese Weise das Skript läuft weiter, auch wenn Sie Ihren Browser schließen oder gehen Sie zu einer anderen Seite.

Denken Sie an Gearman

  

Gearman ist ein allgemeiner Anwendungs-Framework für die Landwirtschaft aus der Arbeit   mehrere Maschinen oder Prozesse. Es ermöglicht es, Anwendungen zu vervollständigen   Aufgaben parallel, Balance Verarbeitung zu laden, und Funktionen aufzurufen   zwischen den Sprachen. Der Rahmen kann in einer Vielzahl von verwendet werden   Anwendungen von hochverfügbaren Web-Site für den Transport von   Datenbank-Replikationsereignisse.

     

Diese Erweiterung stellt Klassen für Gearman Kunden schriftlich und   Arbeitskräfte.   - Source-PHP-Handbuch

Offical Website von Gearman

Neben bastiandoeen Antwort Sie ignore_user_abort(true); mit einer cUrl Anforderung kombinieren .

Gefälschte einer Anfrage Abtreibung ein niedrige CURLOPT_TIMEOUT_MS Einstellung und halte Verarbeitung, nachdem die Verbindung geschlossen:

function async_curl($background_process=''){

    //-------------get curl contents----------------

    $ch = curl_init($background_process);
    curl_setopt_array($ch, array(
        CURLOPT_HEADER => 0,
        CURLOPT_RETURNTRANSFER =>true,
        CURLOPT_NOSIGNAL => 1, //to timeout immediately if the value is < 1000 ms
        CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute
        CURLOPT_VERBOSE => 1,
        CURLOPT_HEADER => 1
    ));
    $out = curl_exec($ch);

    //-------------parse curl contents----------------

    //$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    //$header = substr($out, 0, $header_size);
    //$body = substr($out, $header_size);

    curl_close($ch);

    return true;
}

async_curl('http://example.com/background_process_1.php');

NB

  

Wenn Sie cURL in weniger als einer Sekunde Timeout möchten, können Sie verwenden   CURLOPT_TIMEOUT_MS, obwohl es ein Bug / "Feature" auf „Unix-artigen   Systeme“, die Libcurl führt sofort Timeout, wenn der Wert <   1000 ms mit dem Fehler "cURL Fehler (28): Timeout erreicht wurde". Das   Erklärung für dieses Verhalten ist:

     

[...]

     

Die Lösung ist, um Signale zu deaktivieren mit CURLOPT_NOSIGNAL

Vor

  • Keine Notwendigkeit zu wechseln Methoden (Kompatible Windows & Linux)
  • Keine Notwendigkeit, Verbindung zu implementieren über Kopf- und Puffer (unabhängig von Browser und PHP-Version) Umgang mit

cons

  • Need curl Erweiterung

Ressourcen

Zuk.

Ich bin mir ziemlich sicher, dass dies funktionieren wird:

<?php 

pclose(popen('php /path/to/file/server.php &'));
echo "Server started. [OK]"; 

?>

Die '&' ist wichtig. Es erzählt die Schale nicht für den Prozess zu warten, um zu beenden.

Sie können auch diesen Code in Ihrer PHP verwenden (wie "bastiandoeen", sagte)

ignore_user_abort(true); 
set_time_limit(0);

in der Server-Stopp-Befehl:

<?php

$output;
exec('ps aux | grep -ie /path/to/file/server.php | awk \'{print $2}\' | xargs kill -9 ', $output);
    echo "Server stopped. [OK]";

?>

Rufen Sie StartBuffer () vor jedem Ausgang und EndBuffer (), wenn Sie die Client-Verbindung schließen möchten. Der Code nach EndBuffer () aufgerufen wird auf Server ohne Client-Verbindung ausgeführt werden.

    private function StartBuffer(){
        @ini_set('zlib.output_compression',0);
        @ini_set('implicit_flush',1);
        @ob_end_clean();
        @set_time_limit(0);
        @ob_implicit_flush(1);
        @ob_start();
    }

    private function EndBuffer(){
        $size = ob_get_length();
        header("Content-Length: $size");
        header('Connection: close');
        ob_flush();ob_implicit_flush(1);
    }

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top