有一个系统Linux。它有一个日志。在此日志中有以下格式的条目:
2020-04-24 14:00:58.870+0300:Some log
2020-04-24 14:00:58.872+0300:Some another log
2020-04-24 14:00:58.891+0300:And another
例如,有必要从此日志中获取最后 10 分钟的记录(有时需要花费最后几秒钟)。问题是日志可以分成几行,例如:
2020-04-24 14:00:58.870+0300:Some log
2020-04-24 14:00:58.872+0300:Some
another
log
2020-04-24 14:00:58.891+0300:And another
我试过的:
sed -n "/^$(date --date='10 min ago' '+%Y-%m-%d %H:%M:%S')/,\$p" log.log
该选项很好,但它不执行所需的操作(如果在调用命令的同一秒内没有日志,则不会找到任何内容)。
awk -v from_date="$(date --date='10 min ago' '+%Y-%m-%d %H:%M:%S')" -v to_date="date '+%Y-%m-%d %H:%M:%S'" '$0 > from_date && $0 < to_date || $0 ~ to_date' log.log
此选项更好,可以满足需要,但由于某些日志被分成几行而中断。
正如我看到的问题的解决方案:
1. 计算需要日志的日期
%date% = date --date='10 min ago' '+%Y-%m-%d %H:%M:%S'2.
%строка%从最后一行2.1 的日志中向上。如果开头
%строка%与正则表达式\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}2.1.1 重合。然后
是 2.1.1.1。如果
%строка% > %date%(按字典顺序),则输出所有通过的行;打破循环。
但是因为 我不强,我不知道该怎么做bash。
我的算法草图:
d=$(date --date='10 min ago' '+%Y-%m-%d %H:%M:%S'); tac log.log | (while read -r line; do ([[ $line =~ ([0-9]{4}-[0-9]{2}-[0-9]{2}.*) ]] && [[ "$line" > "$d" ]] && break) || echo $line; done;) | tac -
但在这种情况下,会显示整个日志。
d=$(date --date='10 min ago' '+%Y-%m-%d %H:%M:%S'); tac log.log | (while read -r line; do ([[ $line =~ ([0-9]{4}-[0-9]{2}-[0-9]{2}.*) && $d > $line ]] && (break)) || echo $line; done;) | tac -
在这种情况下,选择了真正必要的日期,但它不起作用break,并且显示的“旧”日志不是从该日期开始的。它也可以工作很长时间,因为我认为日志已被完全读取。
限制:
系统具有只读访问权限。那些。无法在那里上传一些文件、安装一些实用程序、配置现有实用程序的功能。
使用GNU AWK你可以这样做:
如果将问题重新表述为仅获取日志文件中最后添加的行,而不考虑时间格式等,则可以使用 diff 解决整个问题,如下所示:
我们在这里做什么:
该文件的输出可以发送到另一个程序进行传输,例如,发送到 Slack 或其他地方的一般聊天。
即使系统具有只读权限,也可以将旧新的结束日志文件放在
/tmp或的目录中/var/tmp。