web-dev-qa-db-fra.com

Existe-t-il un moyen d'utiliser Shell_exec sans attendre la fin de la commande?

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?

87
ToughPal

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.

140
jitter

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 &");
26
Brent Baisley

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

11
Oytun

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).

8
user275759

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.

6
BI Architect

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
6
Pedro Lobito

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.

1
Alfred

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.

1
chaos