2017-08-04 2 views
1

Je souhaite appeler le proc_open pour exécuter un script en arrière-plan et le processus d'arrière-plan se termine au bout de quelques secondes. Fondamentalement, le script est un script C/Java/Python qui va compiler et exécuter le code soumis par l'utilisateur, donc je veux que le processus puisse être terminé après un certain temps. Ce que je veux réaliser est que quand le temps d'exécution du script exécutant l'arrière-plan dépasse, par exemple 3 secondes, arrêter le processus aussi bien qu'arrêter d'écrire dans le fichier. Disons que je cours une boucle pour écrire 1 million lines d'une chaîne dans un fichier, et à time >= 3 seconds, le processus s'arrête. Quand je récupère le fichier, je vais avoir comme 200k lines de la chaîne. Ensuite, je peux afficher la sortie du fichier dans le navigateur. J'utilise la fonction exec_timeout de https://blog.dubbelboer.com/2012/08/24/execute-with-timeout.html. Ensuite, j'exécute une commande exec_timeout("exec nohup java -cp some_dir compiled_java_file &", 3), le processus d'arrière-plan ne sera pas terminé même s'il dépasse déjà la valeur du délai d'attente, mais il continuera à écrire dans le fichier jusqu'à ce qu'il se termine. Alors seulement je peux renvoyer le résultat au navigateur. Si l'utilisateur soumet un code de fonctionnement infini, le processus resterait suspendu jusqu'à ce que je le tue dans l'instance ec2 linux.PHP proc_open() avec timeout

Une idée de pourquoi il ne fonctionne pas comme prévu? Ou une meilleure fonction disponible pour atteindre mon objectif? Mon application est développée en PHP et hébergée sur AWS Elastic Beanstalk.

Répondre

0

Sur proc_terminate manual, premier utilisateur contribué Notes:

Comme expliqué dans http://bugs.php.net/bug.php?id=39992, proc_terminate() laisse des enfants du processus enfant en marche. Dans mon application, ces enfants ont souvent des boucles infinies, donc j'ai besoin d'un moyen sûr de tuer processus créés avec proc_open(). Lorsque j'appelle proc_terminate(), le processus /bin/sh est supprimé, mais l'enfant avec la boucle infinie est en cours d'exécution.

Sur exec_timeout:

proc_terminate($process, 9); 

devrait être remplacé par:

$status = proc_get_status($process); 
if($status['running'] == true) { //process ran too long, kill it 

    //get the parent pid of the process we want to kill 
    $ppid = $status['pid']; 
    //use ps to get all the children of this process, and kill them 
    $pids = preg_split('/\s+/', `ps -o pid --no-heading --ppid $ppid`); 
    foreach($pids as $pid) { 
     if(is_numeric($pid)) { 
      echo "Killing $pid\n"; 
      posix_kill($pid, 9); //9 is the SIGKILL signal 
     } 
    } 
    proc_close($process); 
} 
+0

J'ai essayé en fait cela et il ne fonctionne pas. Je pense que mon problème est plutôt que le script principal doit attendre que le processus 'background' se termine et que seulement il renvoie le résultat au navigateur. –