I want to call proc_open
to execute a script in the background, and the background process will terminate after a few seconds. Basically, the script is a C/Java/Python script that will compile and run the user submitted code, so I want the process to be able to be terminated after some time.
What I want to achieve is that when the execution time of the background running script exceeds, say 3 seconds, halt the process as well as stop writing to the file. Let's say I run a for loop to write 1 million lines
of some string to a file, and at time >= 3 seconds
, the process stops. When I retrieve back the file, I will get like 200k lines
of string. Then I can display the output of the file back to the browser.
I am currently using the function exec_timeout
from https://blog.dubbelboer.com/2012/08/24/execute-with-timeout.html.
Then I execute a command exec_timeout("exec nohup java -cp some_dir compiled_java_file &", 3)
, the background process will not be terminated even if it already exceeds the timeout value, instead it will continue to write to the file until it completes. Then only I can echo the result back to the browser. If the user submits a infinite running code, the process would just hanging there until I kill it in ec2 linux instance.
Any idea of why it is not functioning as expected? Or any better function available to achieve my goal? My application is developed in PHP and hosted on AWS Elastic Beanstalk.
答案 0 :(得分:0)
在proc_terminate manual上,第一位用户提供了备注:
如http://bugs.php.net/bug.php?id=39992中所述,proc_terminate() 让孩子的孩子进程运行。在我的申请中,这些 孩子们经常有无限的循环,所以我需要一个可靠的方法来杀人 使用proc_open()创建的进程。当我调用proc_terminate()时, / bin / sh进程被终止,但是具有无限循环的子进程是 离开了。
在exec_timeout上:
proc_terminate($process, 9);
应替换为:
$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);
}