【问题标题】:PHP proc_open() with timeoutPHP proc_open() 超时
【发布时间】:2018-01-12 10:23:22
【问题描述】:

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

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

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

知道为什么它没有按预期运行吗?或者有什么更好的功能可以实现我的目标?我的应用程序使用 PHP 开发并托管在 AWS Elastic Beanstalk 上。

【问题讨论】:

    标签: php linux amazon-elastic-beanstalk shell-exec proc-open


    【解决方案1】:

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

    【讨论】:

    • 我确实尝试过,但它不起作用。我认为我的问题更像是主脚本必须等待“后台”进程完成,然后才将结果返回给浏览器。
    • preg_split('/\s+/', ps -o pid --no-heading --ppid $ppid);没有意义
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-03
    • 2021-11-25
    相关资源
    最近更新 更多