システムログを簡単に調査できるjournalctlコマンドのメモ。

grepやawk等でsyslogを頑張って加工しなくても、欲しい情報が得られるかも?

はじめに

  • journalctlはsystemd-journaldによって収集されたログを参照するコマンドである。
  • systemd-journaldは、ジャーナルと呼ばれる構造化されたインデックス付きのログを保存してくれる。
  • 主に以下の手段で取得できる情報をログとして収集してくれる。
    • カーネル
    • ブートプロセス
    • systemdが起動する全てのサービスの標準出力、標準エラー出力
    • syslogプロトコルによって送信されるメッセージ

基本的な使い方

オプションなしでjournalctlを用いると、ジャーナル内のログを表示できる。

$ journalctl
 1月 18 21:07:33 hoge systemd[1193]: Queued start job for default target Main User Target.
 1月 18 21:07:33 hoge systemd[1193]: Created slice User Application Slice.
 1月 18 21:07:33 hoge systemd[1193]: Created slice User Core Session Slice.
 1月 18 21:07:33 hoge systemd[1193]: Reached target Paths.
 1月 18 21:07:33 hoge systemd[1193]: Reached target Timers.
 1月 18 21:07:33 hoge systemd[1193]: Starting D-Bus User Message Bus Socket...

rootユーザであれば全てのジャーナルにアクセスできる。

一般ユーザでもjournalctlは利用できるが、システムによって表示されるログが制限される場合もあるので注意。

なお、ジャーナルは/run/log/journalディレクトリに保持されており、システムのリブート時には削除されてしまう点も注意。

リブート後もジャーナルを保持する場合は、/etc/systemd/journald.confの設定でStorage=persistentとすると、/var/log/journald配下に保持される。

$ sudo vim /etc/systemd/journald.conf
[Journal]
Storage=persistent
$ sudo systemctl restart systemd-journald.service

システムジャーナルをリアルタイムで出力する

tailコマンドと同じ -fを使う。

$ journalctl -f

直近のログを指定した行数分だけ出力する

これもtailコマンドと同じく -n 行数で表示できる。

$ journalctl -n 5

指定したsystemdユニットに関連するログをフィルタする

journalctl -u <systemdユニット名>とする。

検証機でlibvirtd.serviceを指定した際は以下の通りとなった。

$ journalctl -u libvirtd.service
 1月 14 02:09:50 test systemd[1]: Starting Virtualization daemon...
 1月 14 02:09:50 test systemd[1]: Started Virtualization daemon.
 1月 14 02:09:50 test dnsmasq[5344]: started, version 2.86 cachesize 150
 1月 14 02:09:50 test dnsmasq-dhcp[5344]: DHCP, IP range 192.168.122.2 -- 192.168.122.254, lease time 1h
 1月 14 02:10:26 test systemd[1]: libvirtd.service: Deactivated successfully.
 1月 17 01:28:10 test libvirtd[636]: hostname: test

libvirtdだけでなく、systemd等関連するログもフィルタしてくれる。

特定のユニットがわからない場合は以下の方法でジャーナル内のすべてのユニットを表示できる

$ journalctl -F _SYSTEMD_UNIT
libvirt-guests.service
blk-availability.service
systemd-machined.service
session-490.scope
session-489.scope
.
.
.

時間を指定してフィルタする

-Sまたは–sinceを使うことで様々な方法でフィルタできる。

過去○時間のすべてのログを表示する場合

$ journalctl -S -4h

特定の日時を起点にすべてのログを表示する場合

$ journalctl -S '2024-04-10 15:00:00'

特定の日時のログのみを抽出する場合。終わりの日時は-Uまたは–untilで指定する

$ journalctl -S '2024-04-10 15:00:00' -U '2024-04-20 15:00:00'

ログの深刻度・重要度でフィルタする

-pとログレベルもしくは数字を指定することでフィルタできる。

ログレベル 番号
emerg 0
alert 1
crit 2
err 3
warning 4
notice 5
info 6
debug 7
$ journalctl -p 2

以下の通り範囲指定や複数指定もできる。

  • ログレベルalert(1)からwarning(4)の間を表示
$ journalctl -p 1..4
  • errとwarningのみ表示
$ journalctl -p err -p warning

日時の新しい順にログを表示する

-rを使うことで日時を逆順(新しい順)にログを表示できる。

$ journalctl -r

-eを使うと、ページャの最後に移動した状態でログを表示できる。

デフォルトだと1000行分のログが表示される。行数を変えたい場合は、-nオプションで行数を指定する。

  • -nオプションなしの場合
$ journalctl -e

option_e_default

「lines 978/1000/1000(END)」と表示されているように、1000行分のログを表示させ、ページャの最後に移動した状態で表示される。

  • -nオプションありの場合
$ journalctl -e -n200

「lines 178-200/200(END)」と表示されているように、-nで指定した行数が表示される。

option_e_and_n

ブート時のログを表示する

-bでブート時のログを表示させることができる。引数に何も指定しない場合は、最後にブートした際のログが表示される。

$ journalctl -b
10月 05 23:44:17 hoge kernel: BIOS-e820: [mem 0x0000000000000000-0x000000000009efff] usable
10月 05 23:44:17 hoge kernel: BIOS-e820: [mem 0x000000000009f000-0x00000000000fffff] reserved
10月 05 23:44:17 hoge kernel: BIOS-e820: [mem 0x0000000000100000-0x0000000039706fff] usable
10月 05 23:44:17 hoge kernel: BIOS-e820: [mem 0x0000000039707000-0x0000000042b17fff] reserved
10月 05 23:44:17 hoge kernel: BIOS-e820: [mem 0x0000000042b18000-0x0000000042be3fff] ACPI data
10月 05 23:44:17 hoge kernel: BIOS-e820: [mem 0x0000000042be4000-0x0000000042d1efff] ACPI NVS
10月 05 23:44:17 hoge kernel: BIOS-e820: [mem 0x0000000042d1f000-0x00000000437fefff] reserved

引数に負の数を指定すると、指定した回数より前のブートログが表示される。例えば、直近1回前のブートログを表示したい場合は、-1とする。

$ journalctl -b -1

systemd-journaldが保持している過去のブート履歴は–list-bootsで調べることができる。

$ journalctl --list-boots
-15 d4ff1385a6e249d083163f4a041604e0 Thu 2024-01-18 21:07:33 JST—Thu 2024-01-18 23:25:59 JST
-14 20000f34fd1c4bca90ebc2341322c589 Thu 2024-01-18 23:28:02 JST—Sun 2024-03-31 17:16:51 JST
-13 f44ada39a0e54339bae7548f65410b09 Wed 2024-04-03 00:44:02 JST—Wed 2024-04-03 00:44:11 JST
-12 fbbba305c4d045baad6f82d38cbf4d6a Wed 2024-04-03 00:44:57 JST—Sun 2024-04-28 17:33:57 JST
-11 18d74c7c9c6c41a4bb8822f9da257029 Sun 2024-04-28 17:34:23 JST—Sun 2024-04-28 17:40:26 JST
-10 f175d72df5254d6fbd7f79fbe4604a1c Sun 2024-04-28 17:41:02 JST—Sun 2024-04-28 17:44:32 JST
 -9 3fed02a045f84637a0062f96d004e850 Sun 2024-04-28 17:44:57 JST—Sun 2024-05-12 02:40:38 JST
 -8 d99d3af5805742bfa4d1d21a2442fd68 Sun 2024-05-12 02:41:03 JST—Sun 2024-06-09 22:33:57 JST
 -7 aee88964432f497ab90b093c0eb73d69 Sun 2024-06-09 22:57:23 JST—Sun 2024-06-09 22:58:04 JST
 -6 dd8380a9f86948c891a3c3dad7df727c Sun 2024-06-09 23:01:14 JST—Wed 2024-06-12 00:11:48 JST
 -5 d5439d7570ba417d9df3417ba0f5de02 Wed 2024-06-12 00:13:05 JST—Thu 2024-08-01 15:32:35 JST
 -4 8dee204b31a64112879c719c378a1801 Fri 2024-08-02 11:45:10 JST—Fri 2024-08-02 12:13:54 JST
 -3 a4b35eec00204df3b3f3a04efb433665 Fri 2024-08-02 12:14:27 JST—Fri 2024-08-09 15:29:24 JST
 -2 f850749d5d884dbc929039e9843d20b9 Fri 2024-08-09 15:29:49 JST—Sat 2024-10-05 23:40:06 JST
 -1 bac604847b9348eb8230831afe29b5ca Sat 2024-10-05 23:41:19 JST—Sat 2024-10-05 23:43:46 JST
  0 50d2fbdad36742a88cd832115b9d4f91 Sat 2024-10-05 23:44:17 JST—Sat 2024-11-09 11:22:54 JST

カーネルメッセージを表示させる

-kを指定することでカーネルログに絞って表示させることができる。

$ journalctl -k
10月 05 23:44:17 hoge kernel: ACPI: Reserving FACP table memory at [mem 0x42bde000-0x42bde113]
10月 05 23:44:17 hoge kernel: ACPI: Reserving DSDT table memory at [mem 0x42b7f000-0x42bdd2b4]
10月 05 23:44:17 hoge kernel: ACPI: Reserving FACS table memory at [mem 0x42d1b000-0x42d1b03f]
10月 05 23:44:17 hoge kernel: ACPI: Reserving SSDT table memory at [mem 0x42bdf000-0x42be155c]
10月 05 23:44:17 hoge kernel: ACPI: Reserving FIDT table memory at [mem 0x42b7e000-0x42b7e09b]
10月 05 23:44:17 hoge kernel: ACPI: Reserving SSDT table memory at [mem 0x42b7b000-0x42b7de8b]

ログの形式を変更する

-oオプションを用いれば、ログをjson等の形式に変換できる。

$ journalctl -o json
{"JOB_RESULT":"done","_GID":"0","_SYSTEMD_UNIT":"init.scope","_TRANSPORT":"journal","_BOOT_ID":"50d2fbdad36742a88cd832115b9d4f91","INVOCAT>
{"SYSLOG_TIMESTAMP":"Nov  9 11:31:49 ","_HOSTNAME":"hoge","_UID":"0","_CMDLINE":"/usr/sbin/anacron -d -q -s","_PID":"1364354","MESSAGE":"An>
{"_SYSTEMD_CGROUP":"/system.slice/anacron.service","_COMM":"anacron","MESSAGE":"Normal exit
(0 jobs run)","_HOSTNAME":"nuc","_SYSTEMD_UNIT>
{"_UID":"0","_CMDLINE":"/sbin/init splash","PRIORITY":"6","TID":"1","SYSLOG_FACILITY":"3","INVOCATION_ID":"0e0f2b6d6320490d9601c7a6f2456ad>
{"_MACHINE_ID":"1d0413e6503642fa842f22bfc7cb652f","CODE_LINE":"5553","MESSAGE_ID":"7ad2d189f7e94e70a38c781354912448","PRIORITY":"6","_SELI

1行の文字がターミナルにおさまらない場合は、–no-pagerオプションを追加してで1行をマルっと表示させるとよい。

また-o verboseと指定することで、ログを詳細に表示することができる。

  • 例:libvirtdのログを詳細に表示させる
$ journalctl -u libvirtd -n1 -o verbose
Sat 2024-11-09 11:39:02.349005 JST [s=6338cb78f4a0436c82902c2e6d6970bc;i=624a0;b=50d2fbdad36742a88cd832115b9d4f91;m=2b5f2ef1d5f;t=62671c53>
    PRIORITY=6
    SYSLOG_FACILITY=3
    _SELINUX_CONTEXT=unconfined
    _SYSTEMD_SLICE=system.slice
    _BOOT_ID=50d2fbdad36742a88cd832115b9d4f91
    _MACHINE_ID=1d0413e6503642fa842f22bfc7cb652f
    _HOSTNAME=hoge
    _TRANSPORT=syslog
    SYSLOG_IDENTIFIER=dnsmasq-dhcp
    SYSLOG_PID=236956
    _PID=236956
    _UID=125
    _GID=30
    _COMM=dnsmasq
    _EXE=/usr/sbin/dnsmasq
    _CMDLINE=/usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/vagrant-libvirt.conf --leasefile-ro --dhcp-script=/usr/lib/libvirt/lib>
    _CAP_EFFECTIVE=3400
    _SYSTEMD_CGROUP=/system.slice/libvirtd.service
    _SYSTEMD_UNIT=libvirtd.service
    _SYSTEMD_INVOCATION_ID=c2ea43bf14524677b0db1c5f4ac73f7b
    MESSAGE=DHCPREQUEST(virbr2) xxx.xxx.xxx.xxx
    SYSLOG_TIMESTAMP=Nov  9 11:39:02

-oで指定できる他の形式は、man journalctlを参照。

ログに説明ヘルプテキストを表示させる

-xを指定することで、出力されたログに説明ヘルプテキストを付与できる。

ただし、全てのメッセージではなく、一部のサポートされているメッセージのみで利用できる点に注意。

# -xなし
$ journalctl -b
11月 09 11:45:18 hoge systemd[1]: NetworkManager-dispatcher.service: Deactivated successfully.

# -xあり
$ journalctl -b -x
11月 09 11:45:18 hoge systemd[1]: NetworkManager-dispatcher.service: Deactivated successfully.
 subject: unit succeeded
 defined-by: systemd
 support: http://www.ubuntu.com/support

 The unit NetworkManager-dispatcher.service has successfully entered the 'dead' state.

ログをgrepする

-gまたは–grepを指定することで、ログのMESSAGEフィールドでgrepすることができる。

–grepの場合はイコールでgrepしたい文字列を指定する。

$ journalctl -g lib
11月 12 15:15:36 hoge pkexec[1496394]: hoge: Executing command [USER=root] [TTY=unknown] [CWD=/home/user] [COMMAND=/usr/lib/update-notifier/package-system-locked]

$ journalctl --grep=lib
11月 12 15:15:36 hoge pkexec[1496394]: hoge: Executing command [USER=root] [TTY=unknown] [CWD=/home/user] [COMMAND=/usr/lib/update-notifier/package-system-locked]

最後に

上手く使いこなせれば素早く情報をキャッチできそう。

クセでgrepとかを使わないように、journalctlも手に馴染ませておきたい…