systemd 的 journalctl:如何按消息过滤?

systemd 的 journalctl:如何按消息过滤?

日志控制看起来是个查看日志的好工具,但我被一个简单的要求难住了:我想查看所有包含短语的 cron 消息update-ipsets

我当然可以

journalctl -u cron.service | grep update-ipsets

但你会失去 journalctl 输出的所有其他好处(颜色编码、自动分页、实时查看等)。

我试过了:

journalctl -u cron.service MESSAGE=update-ipsets
journalctl -u cron.service "MESSAGE=*update-ipsets*"
journalctl -u cron.service "MESSAGE=.*update-ipsets.*"
journalctl -u cron.service "MESSAGE=/.*update-ipsets.*/"

而且您不想通过点击tab后进行实验MESSAGE=- 挂起(zsh / Debian Jessie)shell并且Ctrl-C也无济于事!

我有点不敢相信它没有内置这个基本功能,所以我确定我一定是错过了什么?

谢谢。

答案1

目前,journalctl 不支持字段匹配中的模式或通配符。grep是您的最佳选择。

我遇到了同样的问题,我认为只有在作为参数传递journalctl时才会搜索 VALUE 的完全匹配。NAME=VALUE

我的调查:

  1. 手册页

    journalctl(1)

    比赛描述中没有提到该模式:

     [...] A match is in the format "FIELD=VALUE", e.g.
     "_SYSTEMD_UNIT=httpd.service", referring to the components
     of a structured journal entry. [...]
    

    -u手册页仅在描述选项时引用模式。

       -u, --unit=UNIT|PATTERN
           Show messages for the specified systemd unit UNIT 
           (such as a service unit), or for any of the units
           matched by PATTERN. 
    
  2. 源代码

    fnmatch中的函数src/journal仅用于搜索单位

  3. 调试日志控制

    启用调试输出您可以看到仅在使用时模式才会扩展-u

    $ SYSTEMD_LOG_LEVEL=debug journalctl -n1 -u gdm*
    ...
    Matched gdm.service with pattern _SYSTEMD_UNIT=gdm*
    Matched gdm.service with pattern UNIT=gdm*
    Journal filter: ((OBJECT_SYSTEMD_UNIT=gdm.service AND _UID=0) OR (UNIT=gdm.service AND _PID=1) OR (COREDUMP_UNIT=gdm.service AND _UID=0 AND MESSAGE_ID=fc2e22bc6ee647b6b90729ab34a250b1) OR _SYSTEMD_UNIT=gdm.service)
    ...
    

    所有匹配均视为精确匹配,包括UNIT

    $ SYSTEMD_LOG_LEVEL=debug journalctl -n1 UNIT=gdm.*
    ...
    Journal filter: UNIT=gdm*
    ...
    

答案2

systemctl --version版本开始237,可能存在带-g/--grep开关的 grep 模式支持,但必须在PRCE2支持的情况下进行编译(似乎没有包含在 Debian Buster 中>=242是需要的,可以从安装buster-backports

journalctl -g ipsets*

即使没有 grep 支持,您仍然可以切换到cat输出模式并使用grep的匹配:

journalctl -b -o cat --no-pager | grep "update-ipsets"

如果你想要一个寻呼机,最好将结果传送到less。你可以使用反向匹配-v / --invert-match来排除某些消息

journalctl -b -o cat --no-pager | grep -v "ACPI" | less

另一个选择是使用json格式:

journalctl -b -o json | jq -C . | less -R

提供详细输出,单行

{
  "SYSLOG_IDENTIFIER": "kernel",
  "_MACHINE_ID": "d72735cff36a41f0a5326f0bb7eb1778",
  "_SOURCE_MONOTONIC_TIMESTAMP": "0",
  "__REALTIME_TIMESTAMP": "1614516018297106",
  "__CURSOR": "s=2b1deb3dba3e42e4a758cc8f011d19c5;i=1;b=c0f6b0e5143a4d3db9f04f00da1a4ff4;m=670dd9;t=5bc64cdc13912;x=ee44184076fc0590",
  "__MONOTONIC_TIMESTAMP": "6753753",
  "SYSLOG_FACILITY": "0",
  "_HOSTNAME": "w16",
  "PRIORITY": "5",
  "_BOOT_ID": "c0f6b0e5143a4d3db9f04f00da1a4ff4",
  "_TRANSPORT": "kernel",
  "MESSAGE": "Linux version 4.19.0-14-amd64 ([email protected]) (gcc version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.171-2 (2021-01-30)"
}

使用jq您可以轻松归档消息:

$ journalctl -b -o json | jq '. | select(._COMM=="sensors")' | jq -r .MESSAGE | less
$ journalctl -b -o json | jq '. | select(._TRANSPORT=="kernel")' | jq -r .MESSAGE | head -n 1
Linux version 4.19.0-14-amd64 ([email protected]) (gcc version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.171-2 (2021-01-30)

答案3

使用 journalctl 版本 247.3-7(作为 systemd),--grep(或 -g)选项允许过滤日志中 MESSAGE 字段包含字符串或匹配正则表达式的行。

man journalctl 说

**-g, --grep=**

           Filter output to entries where the MESSAGE= field matches the specified regular expression. PERL-compatible regular expressions are used, see pcre2pattern(3) for a detailed description of the
           syntax.

           If the pattern is all lowercase, matching is case insensitive. Otherwise, matching is case sensitive. This can be overridden with the --case-sensitive option, see below.

journalctl 手册和 pcre2pattern 中都没有提到,正则表达式必须用单引号或双引号括起来,并且不能有其他字符!!!

如果您以 root 身份或使用 sudo 运行以下命令:

# journalctl --grep "UFW BLOCK"

您将获得所有记录的阻止 ID 和防火墙阻止的请求的列表...

希望这有帮助!

相关内容