2017-08-04 186 views
1

我想调用proc_open在后台执行一个脚本,后台进程将在几秒钟后终止。基本上,该脚本是一个C/Java/Python脚本,它将编译和运行用户提交的代码,所以我希望该流程能够在一段时间后终止。带有超时值的PHP proc_open()

我想实现的是当后台运行脚本的执行时间超过3秒时,停止进程以及停止写入文件。比方说,我运行一个for循环将1 million lines的某些字符串写入文件,并在time >= 3 seconds处停止。当我取回文件时,我会得到字符串200k lines。然后我可以将文件的输出显示回浏览器。

我目前使用的功能exec_timeouthttps://blog.dubbelboer.com/2012/08/24/execute-with-timeout.html。 然后我执行命令exec_timeout("exec nohup java -cp some_dir compiled_java_file &", 3),后台进程即使已超过超时值也不会被终止,而是会继续写入文件直到完成。然后,只有我可以将结果回显给浏览器。如果用户提交了一个无限的运行代码,那么这个进程就会挂在那里,直到我在ec2 linux实例中杀死它为止。

任何想法为什么它没有按预期运作?或者有更好的功能来实现我的目标?我的应用程序是使用PHP开发的,并托管在AWS Elastic Beanstalk上。

回答

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); 
} 
+0

我没有实际尝试这一点,这是行不通的。我认为我的问题更像是主脚本需要等待“后台”过程完成,然后才将结果返回给浏览器。 –