Je gère un script tiers en utilisant une classe wrapper j'ai écrit quels appels Comment est préférable de gérer le délai d'attente sur shell_exec ()? Je pensais à l'envelopper dans un J'ai lu quelques questions ici relatif à L'autre option que j'ai pensée à utiliser une boîte de dialogue modale, avec un spinner de style Ajax tandis que le script fonctionnait, et définir un délai d'attente manuel dans JavaScript. Qui a ensuite donné à l'utilisateur un message de dialogue de modèle à l'abour de l'échec / du délai d'attente et de la fin. P> y a-t-il des méthodes acceptées pour ce cas d'utilisation? P> mon mini test, consistait en ce qui suit, p> Utilisation de cette question comme REF,
Impossible d'exécuter le script php à l'aide de php Exec P> < p> http://www.php.net/manual/fr/function. EXEC.PHP P> P> shell_exec () code> et des tuyaux dans un fichier i analysez plus tard à l'aide du code PHP. Je devrais mentionner que cela fonctionne, mais j'essaie d'améliorer la fonctionnalité, après avoir rencontré un cas d'utilisation que je n'avais pas pensé.
essayer () () code> mais je ne suis pas sûr de la meilleure façon de gérer le composant temporel. P>
shell_exec () code> et
exécuté () code> et il semble que, en passant des paramètres de sortie sur
exécuté () code> Vous pouvez obtenir un retour, Mais cela s'appuie sur le script terminant avec un statut de retour. De plus, dans ma page de test Mini, je ne peux pas sembler l'obtenir de renvoyer une sortie! P>
4 Réponses :
Je vous suggérerais de regarder à l'aide de voir http://www.php.net/manual/fr /function.proc-open.php P> proc_open code>. Vous pouvez la configurer pour renvoyer une ressource de flux, conserver manuellement une minuterie et si la minuterie expire avant la fin du processus, vous pouvez le terminer avec
proc_terminate code>. Si cela complète avant l'expiration de la minuterie, vous pouvez utiliser
proc_close code> puis
stream_get_contents code> pour saisir les données qui auraient été écrites autrement. P>
Merci je vais essayer ça aujourd'hui et vois comment je vais :)
J'ai aussi trouvé cette question très pratique, Stackoverflow.com/Questtions/2603912/...
J'écris un peu de code de travail pour une telle tâche. Fonction renvoie le code de sortie (0 - OK,> 0 - Erreur) et écrit stdout, stardr sur les variables de référence.
/*execute program and write all output to $out terminate program if it runs more than 30 seconds */ execute("program --option", null, $out, $out, 30); echo $out; function execute($cmd, $stdin=null, &$stdout, &$stderr, $timeout=false) { $pipes = array(); $process = proc_open( $cmd, array(array('pipe','r'),array('pipe','w'),array('pipe','w')), $pipes ); $start = time(); $stdout = ''; $stderr = ''; if(is_resource($process)) { stream_set_blocking($pipes[0], 0); stream_set_blocking($pipes[1], 0); stream_set_blocking($pipes[2], 0); fwrite($pipes[0], $stdin); fclose($pipes[0]); } while(is_resource($process)) { //echo "."; $stdout .= stream_get_contents($pipes[1]); $stderr .= stream_get_contents($pipes[2]); if($timeout !== false && time() - $start > $timeout) { proc_terminate($process, 9); return 1; } $status = proc_get_status($process); if(!$status['running']) { fclose($pipes[1]); fclose($pipes[2]); proc_close($process); return $status['exitcode']; } usleep(100000); } return 1; }
J'ai essayé avec Je suis venu avec cela, il devrait fonctionner à la fois sur Windows et Linux maintenant: P> popen () code>, mais il n'y a aucun moyen de mettre fin à la poncse après.
En outre,
stream_get_contents () code> bloque le flux même lorsque vous utilisez stream_set_blocking sous Windows, je devais donc utiliser Fread à la place. De plus, proc_terminate ne fonctionne pas correctement sous Windows. J'ai donc dû utiliser une fonction de tuer alternative.
function execute($command, $timeout = 5) {
$handle = proc_open($command, [['pipe', 'r'], ['pipe', 'w'], ['pipe', 'w']], $pipe);
$startTime = microtime(true);
/* Read the command output and kill it if the proccess surpassed the timeout */
while(!feof($pipe[1])) {
$read .= fread($pipe[1], 8192);
if($startTime + $timeout < microtime(true)) break;
}
kill(proc_get_status($handle)['pid']);
proc_close($handle);
return $read;
}
/* The proc_terminate() function doesn't end proccess properly on Windows */
function kill($pid) {
return strstr(PHP_OS, 'WIN') ? exec("taskkill /F /T /PID $pid") : exec("kill -9 $pid");
}
Si vous êtes sous Linux (ou WSL dans Windows 10), l'utilisation de la commande Timeout semble être la meilleure solution. Voir cette réponse: Exec () avec Timeout P>