J'ai une tâche intensive en processus que j'aimerais exécuter en arrière-plan.
L'utilisateur clique sur une page, le script PHP s'exécute et, enfin, en fonction de certaines conditions, il doit exécuter un script Shell, à savoir E.G .:
Shell_exec('php measurePerformance.php 47 844 [email protected]');
Actuellement, j'utilise Shell_exec , mais , le script doit donc attendre une sortie. Existe-t-il un moyen d'exécuter la commande que je veux sans attendre la fin?
Que diriez-vous d'ajouter.
"> /dev/null 2>/dev/null &"
Shell_exec('php measurePerformance.php 47 844 [email protected] > /dev/null 2>/dev/null &');
Notez que ceci élimine également stdio et stderr.
Ceci exécutera une commande et se déconnectera du processus en cours. Bien sûr, cela peut être n'importe quelle commande que vous voulez. Mais pour un test, vous pouvez créer un fichier php avec une commande sleep (20).
exec("Nohup /usr/bin/php -f sleep.php > /dev/null 2>&1 &");
Vous pouvez également redonner instantanément votre sortie au client et poursuivre le traitement de votre code PHP après.
C’est la méthode que j’utilise pour les appels Ajax en attente qui n’auraient aucun effet sur le côté client:
ob_end_clean();
ignore_user_abort();
ob_start();
header("Connection: close");
echo json_encode($out);
header("Content-Length: " . ob_get_length());
ob_end_flush();
flush();
// execute your command here. client will not wait for response, it already has one above.
Vous pouvez trouver l'explication détaillée ici: http://oytun.co/response-now-process-later
Sous Windows 2003, pour appeler un autre script sans attendre, j'ai utilisé ceci:
$commandString = "start /b c:\\php\\php.EXE C:\\Inetpub\\wwwroot\\mysite.com\\phpforktest.php --passmsg=$testmsg";
pclose(popen($commandString, 'r'));
Cela ne fonctionne qu'après avoir donné des autorisations de changement sur cmd.exe
- ajoute lire et exécuter pour IUSR_YOURMACHINE
_ (J'ai aussi mis write à Deny).
Utilisez la commande popen
de PHP, par exemple:
pclose(popen("start c:\wamp\bin\php.exe c:\wamp\www\script.php","r"));
Cela créera un processus enfant et le script s'exécutera en arrière-plan sans attendre la sortie.
Bien sûr, pour windows
, vous pouvez utiliser:
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("C:/path/to/php-win.exe -f C:/path/to/script.php", 0, false);
Note:
Si vous obtenez une erreur COM
, ajoutez l’extension à votre php.ini
et redémarrez Apache
:
[COM_DOT_NET]
extension=php_com_dotnet.dll
Cela fonctionnera mais vous devrez faire attention à ne pas surcharger votre serveur car cela créera un nouveau processus à chaque fois que vous appelez cette fonction qui s'exécutera en arrière-plan. S'il n'y a qu'un seul appel simultané à la fois, cette solution de contournement fera l'affaire.
Sinon, je vous conseillerais de lancer une file de messages comme par exemple beanstalkd/gearman/Amazon sqs.
Si c'est hors d'une page Web, je vous recommande de générer un signal (en supprimant un fichier dans un répertoire, par exemple) et de laisser un travail cron prendre en charge le travail à effectuer. Sinon, nous risquons d'entrer dans le domaine de l'utilisation de pcntl_fork()
et de exec()
à l'intérieur d'un processus Apache, ce qui est tout simplement mauvais.