像往常一样,我可以syslog
通过以下方式检查条目的内容:
cat /var/log/syslog | grep myentry
我需要将所有myentry
行附加到特定文件。当然,仅将上述命令的输出重定向到文件是行不通的,因为它会附加所有行,即使它们上次已添加。
我想到的第一个解决方案是在所有行之间循环,syslog
直到找到目标文件的最后一行。然后我可以附加以下所有内容。定期执行此操作(即使用 cronjob 或更简单的 bash 中的定时循环)应该可以解决问题。
有没有更聪明或更优雅的方法来完成同样的工作?
编辑
我添加了 terdon 的要求:
我的系统日志示例:
Jan 17 13:03:18 stm32mp1-abc local2.info chat[15782]: CONNECT
Jan 17 13:03:18 stm32mp1-abc local2.info chat[15782]: -- got it
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Ready
Jan 17 13:03:18 stm32mp1-abc local2.info chat[15782]: send (^M)
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Init complete
Jan 17 13:03:18 stm32mp1-abc daemon.info pppd[14362]: Serial connection established.
Jan 17 13:03:18 stm32mp1-abc daemon.info pppd[14362]: Using interface ppp0
我想要附加到的现有文件的示例:
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Ready
我期望这两个文件的最终输出:
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Ready
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Init complete
更新
好吧,看来我需要非常具体以示例为例,无论我的描述如何。新的例子:
系统日志
Jan 17 13:03:18 stm32mp1-abc local2.info chat[15782]: CONNECT
Jan 17 13:03:18 stm32mp1-abc local2.info chat[15782]: -- got it
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Ready
Jan 17 13:03:18 stm32mp1-abc local2.info chat[15782]: send (^M)
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Init complete
Jan 17 13:03:18 stm32mp1-abc daemon.info pppd[14362]: Serial connection established.
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Start operations
Jan 17 13:03:18 stm32mp1-abc daemon.info pppd[14362]: Using interface ppp0
电流输出
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Init complete
新输出
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Init complete
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Start operations
应该清楚:
- 如果
output
文件为空,则追加所有syslog/myentries
行 - 如果
output
文件不为空,则追加所有下一个syslog/myentries
行(来自匹配的行) - 如果
output
文件不为空且没有匹配项,则仍追加所有下一个syslog/myentries
行(最后一个时间戳之后)
如前所述,我可以使用蛮力来完成此操作:循环所有行,检查条件并在需要时追加。
我正在寻找更简单的解决方案,例如syslog
自动拆分条目的提案,但我没有找到方法。
答案1
存储现有目标文件的最后一行。然后使用以下命令向后解析系统日志awk
文件tac
:
p=$(tail -n1 output)
tac syslog | awk -v p="$p" '$0 == p{exit} /myentry/' | tac >> output
当找到最后一行(向后)时,awk
将退出。如果找不到,或者输出最初为空,它将解析整个文件(我假设对于最初为空输出的情况,系统日志中没有空行)。同样,我们通过这种方式搜索所需的最少行,因此预计它对于大文件表现良好。
还要在你的工具箱中保留这个简单有效的命令:
awk '!seen[$0]++' output > output.tmp && mv output.tmp output
您可以随时运行,以修复目标文件,保留顺序(如果出于任何原因重复项设法传递到那里)。
答案2
这是一个简单的方法:
$ awk 'NR==FNR{a[$0]++; next}/myentry/ && !a[$0]' myentries syslog
Jan 17 13:03:18 stm32mp1-abc user.info myentry[14300]: Init complete
这会选择新的匹配行,因此您所需要做的就是重定向到原始文件:
awk 'NR==FNR{a[$0]++; next}/myentry/ && !a[$0]' myentries syslog >> myentries