drg17404 2019-02-11 17:45
浏览 78
已采纳

尾部-f实时输出过程仍在运行

I am trying to do a live output of a file called fail2ban.log this log is on my linux server and i try to proccess it using. The tail process stay opened so it uses loads of cpu performance after some pepoles open the page since the process stay opened

I tried some solution of killing it with

while(true)
{
if($flag === false) die(); // Or exit if you prefer
}

The server is on Apache2

My code :

<?php
echo "Number of banned ip (live) : ";
$hand = popen("grep 'Ban' /var/log/fail2ban.log | wc -l 2>&1", 'r');
while(!feof($hand)) {
    $buff = fgets($hand);
    echo "$buff<br/>
";
    ob_flush();
    flush();
}
pclose($hand);
echo " ";
echo "Current Log (go at the bottom of the page for the live log)";
echo " ";
$output = shell_exec('cat /var/log/fail2ban.log 2>&1');
echo "<pre>$output</pre>";
echo "Live Logs";
echo "<h1> </h1> ";
echo " ";
$handle = popen("tail -f /var/log/fail2ban.log 2>&1", 'r');
while(!feof($handle)) {
    $buffer = fgets($handle);
    echo "$buffer<br/>
";
    ob_flush();
    flush();
}
pclose($handle);
?>

I want it to kill the process when the user quit the page.

  • 写回答

1条回答 默认 最新

  • douzhendi4559 2019-02-11 18:46
    关注

    No @jhnc In this case, popen is guilty, which does not end the process when the program is closed.

    In general, PHP is one of the worst choices to implement tail -f. It's better to use node + websocket.

    In this case, you need to check if something has been added to the file by another method. From http://php.net/manual/en/function.inotify-init.php#101093

    <?php
    /**
    * Tail a file (UNIX only!)
    * Watch a file for changes using inotify and return the changed data
    *
    * @param string $file - filename of the file to be watched
    * @param integer $pos - actual position in the file
    * @return string
    */
    function tail($file,&$pos) {
        // get the size of the file
        if(!$pos) $pos = filesize($file);
        // Open an inotify instance
        $fd = inotify_init();
        // Watch $file for changes.
        $watch_descriptor = inotify_add_watch($fd, $file, IN_ALL_EVENTS);
        // Loop forever (breaks are below)
        while (true) {
            // Read events (inotify_read is blocking!)
            $events = inotify_read($fd);
            // Loop though the events which occured
            foreach ($events as $event=>$evdetails) {
                // React on the event type
                switch (true) {
                    // File was modified
                    case ($evdetails['mask'] & IN_MODIFY):
                        // Stop watching $file for changes
                        inotify_rm_watch($fd, $watch_descriptor);
                        // Close the inotify instance
                        fclose($fd);
                        // open the file
                        $fp = fopen($file,'r');
                        if (!$fp) return false;
                        // seek to the last EOF position
                        fseek($fp,$pos);
                        // read until EOF
                        while (!feof($fp)) {
                            $buf .= fread($fp,8192);
                        }
                        // save the new EOF to $pos
                        $pos = ftell($fp); // (remember: $pos is called by reference)
                        // close the file pointer
                        fclose($fp);
                        // return the new data and leave the function
                        return $buf;
                        // be a nice guy and program good code ;-)
                        break;
    
                        // File was moved or deleted
                    case ($evdetails['mask'] & IN_MOVE):
                    case ($evdetails['mask'] & IN_MOVE_SELF):
                    case ($evdetails['mask'] & IN_DELETE):
                    case ($evdetails['mask'] & IN_DELETE_SELF):
                        // Stop watching $file for changes
                        inotify_rm_watch($fd, $watch_descriptor);
                        // Close the inotify instance
                        fclose($fd);
                        // Return a failure
                        return false;
                        break;
                }
            }
        }
    }
    
    // Use it like that:
    $lastpos = 0;
    $file = '/var/log/fail2ban.log'l
    while (true) {
        echo tail($file,$lastpos);
        ob_flush();
        flush();
    }
    ?>
    

    And you can't forget about max_execution_time and Apache limits

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大