🖖

systemdのjournaldを理解する

2022/07/26に公開

journalの概要

journalはsystemdのログシステム。journalctlコマンドでログ (journal entry) を読むことができる。systemdのserviceとして動いているものなので、次のようにするとjournalのserviceがactiveであることを確認できる。

$ systemctl status systemd-journald.service
● systemd-journald.service - Journal Service
     Loaded: loaded (/usr/lib/systemd/system/systemd-journald.service; static)
     Active: active (running) since Sat 2022-07-23 13:22:08 JST; 3min 15s ago
TriggeredBy: ● systemd-journald-dev-log.socket
             ● systemd-journald-audit.socket
             ● systemd-journald.socket
       Docs: man:systemd-journald.service(8)
             man:journald.conf(5)
   Main PID: 248 (systemd-journal)
     Status: "Processing requests..."
      Tasks: 1 (limit: 18799)
     Memory: 130.6M
        CPU: 860ms
     CGroup: /system.slice/systemd-journald.service
             └─248 /usr/lib/systemd/systemd-journald

...

ログが書き込まれるディレクトリ

私が確認したArch Linuxの場合、/var/log/journal/にログが貯まっていく。/etc/systemd/journald.confStorage=autoになっているとここにロギングされる。

他のディストリビューションはどうなんだろうと思い少し調べたところ、どうも$ man systemd-journaldでmanページのFILESを見ればわかるっぽい。configファイルとログ書き込みファイルの一覧が確認できた。

$ man systemd-journald
...
FILES
       /etc/systemd/journald.conf
           Configure systemd-journald behavior. See journald.conf(5).

       /run/log/journal/machine-id/*.journal, /run/log/journal/machine-id/*.journal~, /var/log/journal/machine-id/*.journal, /var/log/journal/machine-id/*.journal~
           systemd-journald writes entries to files in /run/log/journal/machine-id/ or /var/log/journal/machine-id/ with the ".journal" suffix. If the daemon is stopped uncleanly, or if the files are found to be corrupted, they are renamed using the ".journal~" suffix, and systemd-journald starts writing to a new file.  /run/ is used when /var/log/journal is not available, or when Storage=volatile is set in the journald.conf(5) configuration file.
...

もしこのディレクトリが削除されてもsystemdは同ディレクトリを自動的には作らない。代わりに/run/systemd/journal/に非永続的なログを書き込んでいく。/etc/systemd/journald.confStorage=persistentとして、systemd-journald.serviceをrestartする (またはコンピュータごと再起動する) と、/var/log/journal/が再度作られる。

ちなみにこのディレクトリの中を覗いてみると分かるのだが、ファイルの内容は人間が見るように作られていないようだ。ログを読む場合はjournalctlコマンドを使う。

Priority level / Facility

journalはPriority levelとFacilityによってログを分類する。Priority levelやFacilityはSyslog (RFC5424) で標準化されているものが使われている。(ここらへんに一覧がある。)

Priority level

ログ出力時にはこのpriority levelによって行が色付けされる。

  • 0 = Emergency: system is unusable
  • 1 = Alert: action must be take immediately
  • 2 = Critical: critical conditions
  • 3 = Error: error conditions
  • 4 = Warning: warning conditions
  • 5 = Notice: normal but significant conditions
  • 6 = Informational: informational messages
  • 7 = Debug: debug-level messages

Facility

20以上あるのでいくつかだけ。

  • 0 = kernel messages
  • 1 = user-level messages
  • 2 = mail system
  • 3 = system daemons
  • 4 = security/authorization messages
  • 5 = messages generated internally by syslog
    ...

journalctlのフィルタリング例

いよいよログを出力する。

journalctlをオプションなしで実行すると、journalが保持している全てのログが出力される。ただこれはかなりの量になり得るのであまり気軽に実行しない方が良いかも知れない。journalctlには出力をフィルタリングするための様々なオプションがあるのでこれらを活用するのが良い。

(journalctlの出力はデフォルトでlessに渡される。--no-pagerを付けるとただstdoutに出力されるだけになる。)

-b, --boot

起動してからのログを出力する。

$ journalctl -b

-g, -grep=

MESSAGEフィールドの値を正規表現でgrepする。

$ journalctl --grep=browser

-f, --follow

最新のログのみ表示され、以降新しいログができると追加で出力され続けていく。

$ journalctl -f

-S, --since=, -U, --until=

日時範囲の指定ができる。

$ journalctl --since="2022-07-03 00:00:00"
$ journalctl --since="2022-07-04 00:00:00" --until="2022-07-05 12:00:00"

こんな指定の仕方もできる。

$ journalctl --since="20 min ago"

-k, --dmesg

kernel ring bufferのみ出力する。

$ journalctl -k

-p, --priority=

priority levelの値を指定する。

$ journalctl -p 2

数値だけではなく略称でも指定できる。

$ journalctl -p crit

範囲指定もできる。

$ journalctl -p 0..2

--facility=

facilityの値を指定する。

$ journalctl --facility=1

カンマ区切りで複数のfacilityを指定できる。

$ journalctl --facility=0,1,3

実行ファイルのログ

特定の実行ファイルのログのみ出力する。

$ journalctl /usr/lib/systemd/systemd

オプションの組み合わせ

フィルタリングオプションは組み合わせることができる。

$ journalctl --since="1 week ago" --grep=browser

参照

Discussion