Журнал 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.*/"

И вы не хотите экспериментировать, нажав на вкладку после MESSAGE= - висит (zsh/Debian Jessie) оболочка и Ctrl-C тоже не помог!

Я вроде не могу поверить, что в него не встроена эта базовая функциональность, поэтому я уверен, что я что-то пропустил?

Благодарю.

3 ответа

Решение

В настоящее время 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. [...]
    

    Страница man относится к шаблону при описании -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*
    ...
    

Сsystemctl --versionверсия237может быть поддержка шаблона grep с-g/--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 (debian-kernel@lists.debian.org) (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 (debian-kernel@lists.debian.org) (gcc version 8.3.0 (Debian 8.3.0-6)) #1 SMP Debian 4.19.171-2 (2021-01-30)

В журнале версии 247.3-7 (как systemd) параметр --grep (или -g) позволяет фильтровать строки в журнале, где поле MESSAGE содержит строку или соответствует регулярному выражению.

мужчина 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"

вы получите список всех записанных идентификаторов блоков и запроса, заблокированного брандмауэром...

Надеюсь, это поможет!

Другие вопросы по тегам