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

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

报告相同问题?

悬赏问题

  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码