遭受缓冲之苦

遭受缓冲之苦

我试图使用以下方法限制日志文件中的行数:

php $PWD/private_html/run_worker.php | head -n 20000 >> $PWD/private_html/data/logfile.txt 2>&1 &

如果我运行不带“| head -n 20000”的命令,我的输出将被重定向。但是,当我包含限制代码时,不会将任何内容写入日志。

任何帮助,将不胜感激。

答案1

遭受缓冲之苦

首先,可能会有缓冲;默认情况下,输出到非终端非标准错误是块缓冲的(每个设置vbuf(3))因此,在缓冲区被填满之前,人们不应该期望看到任何日志(或者当某些东西崩溃或吃掉致命信号时根本看不到)。最好使用两个终端进行测试,一个用于运行命令,另一个用于tail -f输出文件:

# terminal watcher (how do the log lines appear in the logfile?)
rm logf; touch logf; tail -f logf

# terminal test commands (feed logfile)
php -r 'while(1){echo "logline\n";sleep(1);}' >> logf
...
^C
perl -E 'while(1){say "logline";sleep 1}' >> logf
...
^C

由此看来(至少在我的系统上)PHP 不会阻止缓冲区标准输出,这与默认设置有所不同;但是,head它会缓冲,但stdbuf没有帮助,因为日志行全部出现在一堆中:

php -r 'while(1){echo "logline\n";sleep(1);}' | head -7 >> logf
php -r 'while(1){echo "logline\n";sleep(1);}' | stdbuf -o 0 -- head -7 >> logf

所以head可能不是完成此任务的正确工具。 (顺便说一句,各种应用程序都会在内部进行缓冲,因此无论stdbuf发生什么可怕的事情都可能无济于事:

stdbuf -o 0 perl -E 'while(1){say "logline";sleep 1}' >> logf
perl -E 'STDOUT->autoflush;while(1){say "logline";sleep 1}' >> logf

如果可能的话,在应用程序本身中设置适当的缓冲。)

至于日志

对日志行的硬限制需要消耗 N 行,但随后保持打开状态(或者应用程序会被杀死,还是......?):

php -r 'while(1){echo "logline\n";sleep(1);}' 2>&1 \
| perl -ne 'BEGIN{STDOUT->autoflush; $N=7 } if($N>0){print;$N--}' >> logf

或者,这可以使用 PHP 在内部完成,假设所有日志都可以通过函数或日志记录模块或框架路由来处理此任务。否则,有一堆记录旋转标准输出的工具,涉及不同级别的选项和学习曲线,尽管这些似乎缺乏“N 行”,而是根据大小设置上限。

相关内容