php - 在 PHP 中对 popen/fgets 施加时间限制

标签 php amazon-web-services tail time-limiting

我想对使用 popen 在 PHP 中打开的 fgets 的进程读取施加时间限制。

我有下一个代码:

$handle = popen("tail -F -n 30 /tmp/pushlog.txt 2>&1", "r");
while(!feof($handle)) {
    $buffer = fgets($handle);
    echo "data: ".$buffer."\n";
    @ob_flush();
    flush();
}
pclose($handle);

我试过没有成功:

set_time_limit(60);
ignore_user_abort(false);

过程如下:

  1. 浏览器发送 GET 请求等待 HTML5 服务器端的应答 事件格式。
  2. 请求由 AWS Load Balancer 接收并且是 转发到 EC2 实例。
  3. 答案是文件的最后 30 行
  4. 浏览器在 30 条消息中收到它并保持连接。
  5. 如果 tail 命令发送一个新行,它会被返回,否则 fgets 会等待未定义的时间,直到从 tail 命令返回新行。
  6. AWS Load Balancer 在网络不活动 60 秒后(60 秒内无新行)关闭与浏览器的连接。与 EC2 实例的连接未关闭。
  7. 浏览器检测到连接已关闭,并打开一个新连接,返回步骤1。

如该步骤所述,AWS Load Balancer 和 EC2 实例之间的连接永远不会关闭,几个小时/几天后,有成百上千个 tail 和 httpd 进程在运行,服务器开始不响应。

当然这似乎是 AWS Load Balancer 错误,但我不想启动一个流程来获得 Amazon 的关注并等待修复。

我的临时解决方案是执行 sudo kill tail 以在服务器变得不稳定之前终止进程。

我认为 PHP 不会停止脚本,因为 PHP 正在“阻塞”等待 fgets 完成。

我知道 AWS Load Balancer 的时间限制是可编辑的,但我想保留默认值,即使更高的限制也无法解决问题。

我不知道是否需要将问题更改为 How to execute a process in linux with a time limit/timeout?。

PHP 5.5.22/Apache 2.4/Linux 内核 3.14.35-28.38.amzn1.x86_64

最佳答案

使用 PHP 5.5.20 测试:

//Change configuration.
set_time_limit(0);
ignore_user_abort(true);

//Open pipe & set non-blocking mode.
$descriptors  = array(0 => array('file', '/dev/null', 'r'),
                      1 => array('pipe', 'w'),
                      2 => array('file', '/dev/null', 'w'));
$process      = proc_open('exec tail -F -n 30 /tmp/pushlog.txt 2>&1',
                                $descriptors, $pipes, NULL, NULL) or exit;
$stream       = $pipes[1];
stream_set_blocking($stream, 0);

//Call stream_select with a 10 second timeout.
$read = array($stream); $write = NULL; $except = NULL;
while (!feof($stream) && !connection_aborted()
        && stream_select($read, $write, $except, 10)) {

    //Print out all the lines we can.
    while (($buffer = fgets($stream)) !== FALSE) {
        echo 'data: ' . $buffer . "\n";
        @ob_flush();
        flush();
    }

}

//Clean up.
fclose($stream);
$status = proc_get_status($process);
if ($status !== FALSE && $status['running'] === TRUE)
    proc_terminate($process);
proc_close($process);

关于php - 在 PHP 中对 popen/fgets 施加时间限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30227531/

相关文章:

javascript - Jquery 更改 ajaxSource 变量

php - 如何使用 PHP 从 AspenTech IP21 Historian 查询数据?

php - 通过比较行来获取两个多维数组之间的差异

ios - 递归上传目录 iOS AWS S3

python - Paramiko/ssh/tail + grep 挂起

php - 如果数据库更改,则全日历自动刷新

mobile - 从移动应用程序下载 AWS S3 内容的安全方式

amazon-web-services - Terraform 获取 vpc 终端节点子网的 IP

linux - unix tty 在尾部用尖音符号 (`) 挂起

linux - 在 Perl 中是否有等同于 `tail -f` 的东西?