PHP Background Processes

j'essaye de faire un script PHP, j'ai fini le script mais ça prend environ 10 minutes pour finir le processus pour lequel il est conçu. Ce n'est pas un problème, mais je suppose que je dois garder la page chargée tout ce temps qui est ennuyeux. Puis-je l'avoir pour commencer le processus et revenir 10 minutes plus tard et juste voir le fichier journal qu'il a généré?

41
demandé sur zuk1 2008-11-05 16:00:50

11 réponses

vous pouvez utiliser" ignore_user_abort (vrai) "

ainsi le script continuera à fonctionner (gardez un oeil sur la durée du script, peut-être ajouter " set_time_limit (0)")

mais un avertissement ici: vous ne pourrez pas arrêter un script avec ces deux lignes:

ignore_user_abort(true); 
set_time_limit(0);

sauf que vous pouvez accéder directement au serveur et y tuer le processus! (Été là, fait une boucle sans fin, se appelant encore et encore, a fait que le serveur est venu à un arrêt de hurlements, a été crié...)

50
répondu bastiandoeen 2011-02-17 14:04:55

sonne comme si vous deviez avoir une file d'attente et un script externe pour traiter la file d'attente.

par exemple, votre script PHP devrait mettre une entrée dans une table de base de données et revenir immédiatement. Ensuite, un cron qui exécute chaque minute vérifie la file d'attente et bifurque un processus pour chaque tâche.

l'avantage est de ne pas verrouiller un fil apache pendant 10 minutes.

26
répondu Gary Richardson 2008-11-05 16:37:29

j'ai eu beaucoup de problèmes avec ce genre de processus sous windows; Ma situation était un peu différente en ce que je ne me souciais pas de la réponse du" script " - je voulais que le script démarre et permette à d'autres requêtes de page de passer pendant qu'il était occupé à travailler ailleurs.

pour une raison ou une autre; j'ai eu des problèmes avec le fait de suspendre d'autres requêtes ou de chronométrer après environ 60 secondes (apache et php ont tous deux été mis à time out après environ 20 minutes); il s'avère également que firefox se termine après 5 minutes (par défaut) de toute façon donc après ce point, vous ne pouvez pas savoir ce qui se passe par le navigateur sans modifier les paramètres de firefox.

j'ai fini par utiliser les méthodes process open et process close pour ouvrir un php en mode cli comme ça:

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

ceci (en utilisant start ) ouvrirait le processus php et ensuite tuerait le processus de démarrage en laissant php fonctionner pour autant de temps qu'il a besoin - encore une fois vous auriez faut tuer le processus manuellement l'arrêter. Il n'avait pas besoin de vous pour définir des temps morts et vous pourriez laisser la page actuelle qui l'a appelé continuer et produire plus de détails.

le seul problème avec ceci est que si vous avez besoin d'envoyer des données au script, soit vous le faites via une autre source, soit vous le passez le long de la" ligne de commande " comme paramètres, ce qui n'est pas aussi sûr.

a bien fonctionné pour ce dont nous avions besoin et assure que le script démarre toujours et est autorisé à s'exécuter sans interruption.

8
répondu Christopher Lightfoot 2008-11-10 11:15:07

cela peut être d'une aide, aussi: asynchrone shell exec in PHP

6
répondu warren 2017-05-23 11:46:52

je pense que la commande shell_exec est ce que vous recherchez.

cependant, il est désactivé en mode de sécurité.

L'article du manuel PHP à ce sujet est ici: http://php.net/shell_exec

il y a un article à ce sujet ici: http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php /

5
répondu genesis 2011-11-13 12:18:56

il y a une autre option que vous pouvez utiliser, exécuter le script CLI...il s'exécute en arrière-plan et vous pouvez même l'exécuter comme une cronjob si vous voulez.

E. g

> #!/usr/bin/php -q

<?php

//process logs

?>

cela peut être configuré comme un cronjob et s'exécutera sans limitation de temps....ces exemples concernent le système d'exploitation unix.

pour information J'ai un script php tournant avec une boucle infinie qui fait un peu de traitement et a été lancé pour les 3 derniers mois non stop.

4
répondu Ronald Conco 2009-11-09 14:36:30

vous pourriez utiliser ignore_user_abort() - de cette façon, le script continuera de fonctionner même si vous fermez votre navigateur ou si vous allez sur une page différente.

3
répondu Greg 2008-11-05 13:09:49

"Gearman

Gearman est un cadre d'application générique pour l'agriculture de travail pour machines ou processus multiples. Il permet aux demandes de compléter tâches en parallèle, pour le traitement de l'équilibre de charge, et pour les fonctions d'appel entre les langues. Le cadre peut être utilisé dans une variété de applications, des sites web à haute disponibilité au transport de réplication de base de données des événements.

cette extension fournit des classes pour écrire des clients Gearman et travailleur. - Source manuel php

site officiel de Gearman

2
répondu Gowri 2013-06-25 14:32:07

en plus de la réponse de bastiandoeen, vous pouvez combiner ignore_user_abort(true); avec une cUrl request .

Faux une demande d'avortement en fixant un bas CURLOPT_TIMEOUT_MS et garder le traitement après la connexion fermée:

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

si vous voulez cURL à timeout en moins d'une seconde, vous pouvez utiliser CURLOPT_TIMEOUT_MS, bien qu'il y ait un bug/"Fonctionnalité" sur "Unix-like les systèmes " qui provoquent l'arrêt immédiat de libcurl si la valeur est < 1000 ms avec l'erreur "cURL Error (28): Timeout was reached". Le l'explication de ce comportement est:

[...]

la solution consiste à désactiver les signaux en utilisant CURLOPT_NOSIGNAL

pros

  • Pas besoin de changer de méthodes (Compatible windows & linux)
  • pas besoin de mettre en œuvre la gestion de la connexion via les en-têtes et la mémoire tampon (indépendamment de la version du navigateur et de PHP)

cons

  • Besoin d'extension curl

ressources

2
répondu RafaSashi 2017-05-23 12:34:09

Zuk.

je suis sûr que ça va marcher:

<?php 

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

?>

le " & " est important. Il indique au shell de ne pas attendre la fin du processus.

vous pouvez également utiliser ce code dans votre php (comme" bastiandoeen "dit)

ignore_user_abort(true); 
set_time_limit(0);

dans la commande d'arrêt de votre serveur:

<?php

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

?>
1
répondu Nader 2014-01-11 13:55:39

il suffit d'appeler StartBuffer() avant toute sortie, et EndBuffer() lorsque vous voulez que le client ferme la connexion. Le code après avoir appelé EndBuffer () sera exécuté sur le serveur sans connexion client.


    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);
    }

-1
répondu user3684669 2018-07-26 13:46:24