我有一个系统日志,看起来像:
[timestamp]: [eventA] the system has started.
[timestamp]: [eventB] eventB detail is stored at <filepath>
<filepath>
看起来像"/var/usr/eventB_timestamp.txt"
我通常不会查看整个日志,因为它是不断生成的,所以我通常使用"tail -F <logpath>
"来查看这些事件。例如,主要的困难是我必须手动打开<filepath>
才能看到事件B。这是非常低效的。如何替换消息行:
[timestamp]: [eventB] eventB detail is stored at <filepath>
带有
[timestamp]: [eventB] + content of <filepath>
我想到了一些单独的东西——grep
然后是sed/awk
。由于我是shell脚本的新手,有可靠的方法可以实现这一点吗?谢谢
要打开相应记录详细文件的最后一个实例,可以执行此
tail ... | tac | awk '/eventB/{print $NF; exit}' | xargs cat
反转输出,找到第一个模式,提取文件名并打印内容。
/tmp/test/file.log:
[timestamp]: [eventA] the system has started.
[timestamp]: [eventB] eventB detail is stored at /tmp/test/evenlog.file
[timestamp]: [eventC] foo foo foo.
/tmp/test/evenlog.file:
line 1
line 2
line 3
运行命令:
sed 's/(.*[eventB].*stored.at.)(.*)/printf [*EventB*]:;cat 2 | xargs echo /e' /tmp/test/file.log
输出:
[timestamp]: [eventA] the system has started.
[*EventB*]:line 1 line 2 line 3
[timestamp]: [eventC] foo foo foo.
问候,
这就是您想要的吗?
#!/bin/sh
tail -F logfile | while read line; do
echo "$line"
case "$line" in
*"eventB detail is stored at"*)
filepath="${line##* }"
if [ -f "$filepath" ]; then
sed 's/^/ /' "$filepath"
else
echo "ERROR: file missing"
fi
;;
esac
done
这会跟踪日志,读取并打印每一行,然后对于与模式匹配的行,将该行的最后一个字作为$filepath
,如果存在同名文件,则打印该文件。。indended,为了你的阅读乐趣。
您可以在awk中实现相同的功能,只需较少的键入:
tail -F logfile | awk '
1;
/eventB detail is stored at/ {
file=$NF
while (getline < file) {
printf("t%sn", $0);
}
close(file)
}
'
请注意,如果有问题的文件不存在,这个awk解决方案会非常失败。因此,如果你使用awk解决方案,这可能是你的起点,但不应该是你的最终解决方案。YMMV。不对使用或误用负责。可能含有螺母。