按日期或日期范围筛选任何系统日志文件。

我想要达到的目标:

我想要按日期筛选系统日志文件,即当我执行以下操作时:

$ cat /var/log/syslog | grep -i "error\|warn\|kernel" 

它打印出像这样的行,比如说最近三天:
(...)
Apr  3 06:17:38 computer_name kernel: [517239.805470] IPv6: ADDRCONF(NETDEV_CHANGE): wlp3s0: link becomes ready
(...)
Apr  4 19:34:21 computer_name kernel: [517242.523165] e1000e: enp0s25 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
(...)
Apr  5 09:00:52 computer_name kernel: [517242.523217] IPv6: ADDRCONF(NETDEV_CHANGE): enp0s25: link becomes ready

如何使用grep(选择或过滤):
- 按日期? - 按日期+小时?
我尝试了什么:
$ cat /var/log/syslog | grep -i "Apr  5" | grep -i "error\|warn\|kernel" 

syslog文件上按预期工作,但在kern.log文件上却不行,例如,它只返回:Binary file (standard input) matches。当我使用tail命令查看这个特定文件时,我可以看到与syslog文件中相同的起始日期格式。

问题:

如何在其他日志文件(如kern.log文件)上实现相同的效果?

此外,是否可以进行以下过滤:

  • 按日期范围过滤?
  • 按日期+小时范围过滤?

提示:如果可能的话,请使用“易于记忆的命令”。

3个回答

systemd给我们提供了journalctl,它允许像这样进行过滤:
journalctl --since "2 days ago"  
journalctl --since "today"
journalctl --since "yesterday --until "today" 
journalctl --since "2019-03-10" --until "2019-03-11 03:00"
journalctl -b # since last boot 
journalctl -k # kernel messages
journalctl -p err # by priority like (emerg|alert|crit|err|warning|info|debug)
journalctl -u sshd # for a particular unit 
journalctl _UID=1000 # for a particular user id

例子可以结合起来!


5好的,现在这太酷了! - George Udosen
2通常甚至不需要使用sudo(特别是如果用户是adm组的成员,而“主要”用户通常都是)。 - PerlDuck

一般来说,kern.log是一个文本文件。但有时候它可能包含一些二进制数据,特别是当系统在崩溃之前无法正确关闭文件时。你可能会注意到一些包含类似于^@^@^@^@^@^@^@^@^@的文本行。
如果grep发现输入是二进制文件,通常会停止进一步处理,并打印... binary file ...。但有一个开关可以改变这种行为。根据manpage的说明:
[...]
File and Directory Selection
   -a, --text
          Process a binary file as if it were text; 
          this is equivalent to the --binary-files=text option.
[...]
你可以尝试以下方法:
$ grep -a -i "Apr  5" /var/log/kern.log  | grep -i "error\|warn\|kernel"

(但实际上,我更喜欢另一个答案中提到的 journalctl 解决方案。)

有一个方便的日志文件查看器叫做lnav,它支持许多过滤选项,包括输入/输出过滤和时间过滤。
安装方法:(确保启用了Universe存储库)
sudo apt install lnav

要按日期进行筛选,请使用内部命令:
:hide-lines-after <date>
:hide-lines-before <date>

日期范围是通过以下命令重置的:
:show-lines-before-and-after

这些是通过按下:然后输入命令来调用的,并且可以与任何关键字的in/out过滤器结合使用。
我希望有一种更简单的方法来按日期进行过滤,但目前这似乎是最好的方式。