2017-08-04 8 views
1

Ich möchte proc_open aufrufen, um ein Skript im Hintergrund auszuführen, und der Hintergrundprozess wird nach ein paar Sekunden beendet. Im Grunde ist das Skript ein C/Java/Python-Skript, das den vom Benutzer eingereichten Code kompiliert und ausführt. Daher möchte ich, dass der Prozess nach einiger Zeit beendet werden kann.PHP proc_open() mit Timeout

Was ich erreichen möchte, ist, dass, wenn die Ausführungszeit des laufenden Skripts im Hintergrund, sagen wir 3 Sekunden, den Prozess anhalten sowie aufhören, in die Datei zu schreiben. Nehmen wir an, ich führe eine for-Schleife aus, um 1 million lines einer Zeichenfolge in eine Datei zu schreiben, und unter time >= 3 seconds stoppt der Prozess. Wenn ich die Datei zurückbekomme, werde ich wie 200k lines von String erhalten. Dann kann ich die Ausgabe der Datei zurück zum Browser anzeigen.

Ich verwende derzeit die Funktion exec_timeout von https://blog.dubbelboer.com/2012/08/24/execute-with-timeout.html. Dann führe ich einen Befehl exec_timeout("exec nohup java -cp some_dir compiled_java_file &", 3) aus, der Hintergrundprozess wird nicht beendet, auch wenn er den Zeitüberschreitungswert bereits überschreitet, stattdessen wird er weiterhin in die Datei schreiben, bis sie abgeschlossen ist. Dann kann nur ich das Ergebnis zurück zum Browser wiedergeben. Wenn der Benutzer einen unendlichen Ausführungscode eingibt, würde der Prozess einfach dort hängen bleiben, bis ich ihn in der ec2-Linux-Instanz beenden würde.

Jede Idee, warum es nicht wie erwartet funktioniert? Oder eine bessere Funktion, um mein Ziel zu erreichen? Meine Anwendung wurde in PHP entwickelt und auf AWS Elastic Beanstalk gehostet.

Antwort

0

Auf proc_terminate manual, erste Nutzer Notizen beigetragen:

Wie in http://bugs.php.net/bug.php?id=39992, proc_terminate() Blätter Kinder des Kindes Prozess läuft. In meiner Anwendung haben diese Kinder oft Endlosschleifen, also brauche ich einen sicheren Weg, um Prozesse mit proc_open() erstellt zu töten. Wenn ich proc_terminate() aufrufe, wird der /bin/sh-Prozess beendet, aber das untergeordnete Element mit der Endlosschleife wird wird ausgeführt.

Auf exec_timeout: ich tatsächlich versuchen, diese habe

$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

und es funktioniert nicht:

proc_terminate($process, 9); 

sollte ersetzt werden. Ich denke, mein Problem ist eher, dass das Hauptskript auf den "Hintergrund" -Prozess warten muss und dann nur das Ergebnis zurück an den Browser sendet. –