我有一个./program
输出大量日志消息并且我的 VPS 上的存储空间非常有限的系统:
我希望我的日志文件包含仅限最新的 N 行 每时每刻(或者更确切地说,当我终止^C我的程序时或者当它崩溃时...)
答:是的。不是想要以下内容:
“将输出重定向到(日志)文件,然后
tail
仅保留最后 N 行。”好吧,日志文件仍然会占用宝贵的空间,直到我运行
tail
它为止,这变得毫无意义......如果别无选择,我可以设置一个 cronjob 来定期执行它,但我想首先探索一下可能性。“使用
logrotate
“”。logrotate
似乎是解决问题的正确方法,但太麻烦了,我想要更简单的方法,最好是可以使用管道和重定向来完成的方法。
B.我尝试了以下方法:
(替换./program
为seq 1000000
if 进行测试)
seq 1000000 | tee /dev/fd/2 | tail -n 10 > logfile
当它自行终止时,工作正常,但当我^C自己中断它时,它
logfile
是空的(而我期望它包含打印在屏幕上的最后 10 行tee
)mkfifo fifo; tail fifo -n 10 > logfile & seq 1000000 | tee fifo
当它自行终止时,工作正常,但当我^C自己中断它
logfile
时,不是空的,但也不包含屏幕上打印的最新日志条目:
。
$ tail fifo -n 10 > logfile & seq 1000000 | tee fifo
[1] 2616
1
2
3
⋮
480178
480179
480180
480181
480182
480183
^C
[1]+ Done tail fifo -n 10 > logfile
$ cat logfile
479297
479298
479299
479300
479301
479302
479303
479304
479305
在这里你可以看到最新的条目是 48 万,而最新的条目logfile
是 479,305... 这意味着我错过了 878 条最新的行!我认为这与缓冲有关,但我不确定。
有人能告诉我如何仅使用 shell 和(最好是标准的)Linux 实用程序来做到这一点吗?谢谢!
答案1
对于您的情况来说,最简单的解决方案可能是具有固定大小的循环日志。
如果你使用的是 Linux,你可以尝试内核模块emlog
emlog 内核模块实现了简单的字符设备驱动程序。该驱动程序的作用类似于具有有限循环缓冲区的命名管道。缓冲区的大小很容易配置。随着更多数据写入缓冲区,最旧的数据将被丢弃。从 emlog 设备读取的进程将首先读取现有缓冲区,然后在写入新文本时查看它,类似于使用“tail -f”监视日志文件。(如果进程需要获取日志的当前内容而不阻塞以等待新数据,则还支持非阻塞读取。)
在 BSD 系统上请参见CLOG(8)