我正在努力想出一个unix命令管道,它允许我只将程序输出的最新 n 行记录到文本文件中。
文本文件的长度不应超过 n 。 (首次填写文件时可能会少一些)
它将在内存/资源有限的设备上运行,因此保持文件大小是一个优先事项。
我尝过这样的东西(n = 500):
program_spitting_out_text > output.txt
cat output.txt | tail -500 > recent_output.txt
rm output.txt
或
program_spitting_out_text | tee output.txt | tail -500 > recent_output.txt
显然两件都不适合我的目的......
任何人都有一个很好的方法在单行中做到这一点?或者我是否必须编写脚本/实用程序?
注意:我不想与dmesg有任何关系,必须使用标准的BSD unix命令。 “program_spitting_out_text”每秒打印约60行/秒。
提前致谢!
答案 0 :(得分:2)
如果program_spitting_out_text
持续运行并保持文件打开,那么你可以做很多事情。
即使删除文件也无济于事,因为它仍会继续写入现在的“隐藏”文件(数据仍然存在,但没有目录条目),直到它关闭它,此时它将真的除去。
如果它关闭并定期重新打开日志文件(每行或每十秒或其他),那么你有一个相对容易的选择。
只需监控文件,直到达到一定的大小,然后滚动文件,例如:
while true; do
sleep 5
lines=$(wc -l <file.log)
if [[ $lines -ge 5000 ]]; then
rm -f file2.log
mv file.log file2.log
touch file.log
fi
done
此脚本将每五秒检查一次文件,如果是5000行或更多,则会将其移动到备份文件。写入它的程序将继续写入该备份文件(因为它具有打开的句柄),直到它关闭它,然后它将重新打开新文件。
这意味着您将在日志文件集中始终拥有(大致)五到一万行,并且您可以使用组合这两行的命令搜索它们:
grep ERROR file2.log file.log
另一种可能性是,如果您可以定期重新启动程序而不影响其功能。举例来说,可以在没有问题的情况下重新启动一个程序,该程序每秒查找一次文件的存在并报告该文件。一个计算PI到一千亿有效数字的人可能不可以在没有影响的情况下重新启动。
如果 可重启,那么你基本上可以采用与上面相同的技巧。当日志文件达到一定大小时,杀死当前程序(您将从脚本中作为后台任务启动),在滚动日志文件时执行所需的任何魔术,然后重新启动程序。
例如,考虑以下(可重启)程序prog.sh
,它只是连续输出当前日期和时间:
#!/usr/bin/bash
while true; do
date
done
然后,以下脚本将负责根据需要启动和停止其他脚本,方法是每隔五秒检查一次日志文件,看它是否超出了限制:
#!/usr/bin/bash
exe=./prog.sh
log1=prog.log
maxsz=500
pid=-1
touch ${log1}
log2=${log1}-prev
while true; do
if [[ ${pid} -eq -1 ]]; then
lines=${maxsz}
else
lines=$(wc -l <${log1})
fi
if [[ ${lines} -ge ${maxsz} ]]; then
if [[ $pid -ge 0 ]]; then
kill $pid >/dev/null 2>&1
fi
sleep 1
rm -f ${log2}
mv ${log1} ${log2}
touch ${log1}
${exe} >> ${log1} &
pid=$!
fi
sleep 5
done
此输出(来自两个日志文件中的每秒wc -l
)显示切换时发生的情况,并指出它仅是近似值,因为切换涉及延迟:
474 prog.log 0 prog.log-prev
496 prog.log 0 prog.log-prev
518 prog.log 0 prog.log-prev
539 prog.log 0 prog.log-prev
542 prog.log 0 prog.log-prev
21 prog.log 542 prog.log-prev
现在请记住这是一个示例脚本。它相对智能,但可能需要一些错误处理,以便在关闭监视器时不会使可执行文件继续运行。
最后,如果这些都不够,那么就没有什么可以阻止你编写自己的过滤程序,该程序接受标准输入并连续输出到真正的环形缓冲区文件。
然后你会做:
program_spitting_out_text | ringbuffer 4096 last4k.log
该程序可能是一个真正的环形缓冲区,因为它将4k文件视为循环字符缓冲区,但是,当然,您需要在文件中使用特殊标记来指示写入点,以及程序可以把它变回真正的流。
或者,它可以与上面的脚本完全相同,重写文件,使其始终低于所需的大小。