1. 序章

当社のサービスの1つで問題をデバッグまたは解決する際、通常、最初に確認したいのは、システムとサービスのログです。 これを行っている間、可能な限り具体的にし、さまざまなソースからの何千ものログエントリをふるいにかけることを避けたいと考えています。

ほとんどの主要なLinuxディストリビューションは、サービスとシステムコンポーネントの管理にsystemdを使用しています。 したがって、Linuxシステムでログを効果的にチェックできるようにするには、ログマネージャーユーティリティjournalctlがどのように機能するかを知る必要があります。

この記事では、 journalctl ツールを使用して、Linuxシステムのログをチェック、フィルタリング、およびクリーンアップする方法を説明します。

2. 基本的なjournalctlコマンド

systemd は、システムログとサービスログをバイナリ形式で保存します。 つまり、 cat tail grep sed awk[などの通常のテキスト処理ツールは使用できません。 X127X]ログはプレーンテキストファイルとして保存されないため、ログを直接読み取ることができます。

したがって、最初にログを読み取って出力するには、journalctlコマンドラインツールが必要です。 まず、いくつかの基本的なjournalctlコマンドを見てみましょう。

2.1. ブーツ

journalctl は、システムの特定の起動によってログを取得できます。

ブーツのリストを取得するには、次を実行してみましょう。

$ journalctl --list­-boots

-136 6e7ae03aa08a4887a6dc376a30ef1fdb Mon 2020-10-12 00:59:31 +03—Mon 2020-10-12 01:02:06 +03
-135 5e8f616769aa4413b198ef30277bf628 Mon 2020-10-12 01:02:38 +03—Mon 2020-10-12 02:55:47 +03
-134 7b839631c6b54dba8e183a0a91f4fa51 Mon 2020-10-12 02:56:29 +03—Wed 2020-10-14 00:16:38 +03
..
-3 539bf36b695f4d69b3474e1efad9f6e6 Wed 2021-01-27 10:25:02 +03—Wed 2021-01-27 20:46:49 +03
-2 d16424126db24a34b6079b933d0cc09a Wed 2021-01-27 20:47:43 +03—Wed 2021-01-27 23:53:16 +03
-1 d4ca259000374bb9a14e383df551aa6e Thu 2021-01-28 10:15:03 +03—Fri 2021-01-29 20:48:03 +03
0 041a418db54e47fabc646e35da606902 Fri 2021-01-29 20:48:41 +03—Sat 2021-01-30 20:57:10 +03

ご覧のとおり、このシステムの最初の起動は-136回目で、最後の起動は0です。 各ブートには、個別のハッシュ値もあります。

現在のブートのすべてのログを取得するには、次を実行してみましょう。

$ journalctl -b

..
Jan 29 20:48:43 fcivaner-ThinkPad-T480s systemd[1]: Starting Authorization Manager...
Jan 29 20:48:43 fcivaner-ThinkPad-T480s systemd[1]: Reached target Bluetooth.
Jan 29 20:48:43 fcivaner-ThinkPad-T480s grub-common[1146]: ...done.
Jan 29 20:48:43 fcivaner-ThinkPad-T480s systemd[1]: Started LSB: Record successful boot for GRUB.
Jan 29 20:48:43 fcivaner-ThinkPad-T480s apport[1111]: ...done.
Jan 29 20:48:43 fcivaner-ThinkPad-T480s systemd[1]: Started LSB: automatic crash report generation.
Jan 29 20:48:43 fcivaner-ThinkPad-T480s polkitd[1203]: started daemon version 0.105 using authority implementation `local' version `0.105'
Jan 29 20:48:43 fcivaner-ThinkPad-T480s dbus-daemon[1115]: [system] Successfully activated service 'org.freedesktop.hostname1'
Jan 29 20:48:43 fcivaner-ThinkPad-T480s systemd[1]: Started Hostname Service.
Jan 29 20:48:43 fcivaner-ThinkPad-T480s NetworkManager[1141]: <info> [1611942523.8157] NetworkManager (version 1.10.6) is starting... (for the first time)
..

表示されるログエントリは、すべてのサービスからのものであり、1つのログにまとめられています。 システムが起動する初期段階で、 systemd がBluetoothに関連するサービスを起動し、次にポリシーキット( polkitd )が起動していることがわかります。私たちのネットワークマネージャー。

前回の起動からすべてのログエントリを取得するには、次を実行してみましょう。

$ journalctl -b -1

Jan 28 10:15:03 fcivaner-ThinkPad-T480s kernel: microcode: microcode updated early to revision 0xe0, date = 2020-06-17
Jan 28 10:15:03 fcivaner-ThinkPad-T480s kernel: Linux version 5.4.0-64-generic (buildd@lgw01-amd64-030) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #72~18.04.1-Ubuntu SMP Fri Jan 15 14:06:34 UTC 2021 
Jan 28 10:15:03 fcivaner-ThinkPad-T480s kernel: Command line: BOOT_IMAGE=/boot/vmlinuz-5.4.0-64-generic root=UUID=19112d3d-1e88-45c7-be9a-a0d3119a8b18 ro quiet splash vt.handoff=1
Jan 28 10:15:03 fcivaner-ThinkPad-T480s kernel: KERNEL supported cpus:
Jan 28 10:15:03 fcivaner-ThinkPad-T480s kernel: Intel GenuineIntel
Jan 28 10:15:03 fcivaner-ThinkPad-T480s kernel: AMD AuthenticAMD
Jan 28 10:15:03 fcivaner-ThinkPad-T480s kernel: Hygon HygonGenuine
Jan 28 10:15:03 fcivaner-ThinkPad-T480s kernel: Centaur CentaurHauls
Jan 28 10:15:03 fcivaner-ThinkPad-T480s kernel: zhaoxin Shanghai 
Jan 28 10:15:03 fcivaner-ThinkPad-T480s kernel: x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'...
...

ブートリストからわかるように、現在のブートのインデックスは常に0であり、最後のブートのインデックスは常に-1です。 -b 引数の後に指定することで、特定のブートのログを確認できます。

2.2. 日付または時刻によるフィルタリング

ログを時間でフィルタリングする場合は、 –sinceおよび–untilパラメーターを使用できます。 先に進んで試してみましょう:

$ journalctl --sinc­e="2­021­-01-30 18:17:16"

Jan 30 18:33:53 fcivaner-ThinkPad-T480s wpa_supplicant[1153]: wlp61s0: WPA: Group rekeying completed with 18:31:bf:c2:98:40 [GTK=CCMP]
Jan 30 18:34:01 fcivaner-ThinkPad-T480s CRON[12094]: pam_unix(cron:session): session opened for user root by (uid=0)
Jan 30 18:34:01 fcivaner-ThinkPad-T480s CRON[12095]: (root) CMD ( test -x /etc/cron.daily/popularity-contest && /etc/cron.daily/popularity-contest --crond)
Jan 30 18:34:01 fcivaner-ThinkPad-T480s CRON[12094]: pam_unix(cron:session): session closed for user root
Jan 30 18:36:58 fcivaner-ThinkPad-T480s kernel: wlp61s0: AP 18:31:bf:c2:98:40 changed bandwidth, new config is 2417 MHz, width 1 (2417/0 MHz)
...

相対時間パラメータを使用して、すばやくフィルタリングすることもできます。

$ journalctl --since "20 min ago"
...

時間解析がどのように機能するかについては、systemd時間仕様を参照してください。

3. さらに絞り込む

3.1. ユニット

systemd は、リソース(サービス、ソケット、マウントなど)をユニットとして識別します。 -uフラグを使用して、特定のユニットのログを取得できます:

$ journalctl -u netcfg

1つまたは複数のユニットに一致するパターンを指定することもできます。 たとえば、「systemd-」で始まるすべてのユニットのログを表示するには、次のコマンドを実行します。

$ journalctl -u systemd-*

ユニットがシステムサービスではなく、ユーザーとして定義したサービスである場合、以下を使用してそのログを確認できます。

$ journalctl --user-unit my-application

–user-unit を使用すると、自分のユーザーに関連付けられているユニットのログしか表示されないことに注意してください。

3.2. ユーザーとプロセス

特定のユーザーIDまたは特定のプロセスIDに属するユニットのメッセージをフィルタリングすることもできます。

$ jour­nalctl _UID=100
$ journalctl _PID=1

3.3. 優先順位

エラーや警告など、特定の優先度レベルのメッセージを表示したい場合もあります。

$ journalctl -p err..alert

メッセージのフィルタリングに使用できるコードは次のとおりです。

コード 優先順位
0 emerg
1 アラート
2 クリティカル
3 エラー
4 警告
5 知らせ
6 情報
7 デバッグ

プロセスは、各ログメッセージに適切なレベルのプレフィックス(「<4>」や「 警告の場合) systemd 各ログメッセージのログレベルを認識します。 そうしないと、このフィルタリングはそのプロセスのログに対して機能しません。

4. ログのテーリングとフォロー

ログを印刷する代わりに追跡するには、次を使用します。

$ journalctl -f

たとえば、サービスapacheのログを追跡するとします。 実行してみましょう:

$ journalctl -f -u apache

最後の10個のログメッセージを出力するには、-nパラメータを使用します。

$ journalctl -u apache -n 10

5. ポケットベルを無効にして直接出力を取得する

ログをファイルに送信したり、処理のために別のプログラムにパイプしたり、単に別のポケットベルを使用したりする場合があります。 この場合、 –no-pager オプションを使用して、journalctlがログを調べるためにページャーを自動的に開かないようにすることができます。

$ journalctl --no-pager

less をポケットベルとして使用するには、次のことを試してみましょう。

$ journalctl --no-pager | less -S

6. ログの真空化

時間の経過とともに、システムのログが非常に大きくなり、問題が発生する可能性があります。 これらの問題は、ディスクスペースの問題から、システムを完全にクラッシュさせるまでの範囲に及ぶ可能性があります。

幸い、 journalctl を使用して、古いログをすばやくクリーンアップできます。 たとえば、ログをクリーンアップしてディスク容量の使用量を100 MB未満にするには、次を使用できます。

journalctl --vacu­um-­siz­e=100M

または、 2週間より古いデータが含まれないようにログをクリーンアップするには、次を使用できます。

journalctl --vacu­um-­tim­e=2­weeks

journaldは、ログをバキュームできるように、以前にログを「アーカイブ済み」としてマークしておく必要があることに注意してください。 これは、 journald 構成ファイル( /etc/systemd/journald.conf )で定義したパラメーターによって期限切れになった後にのみ実行されます。

これらのパラメータは次のとおりです。

  • SYSTEMKEEPFREE
  • RUNTIMEKEEPFREE
  • SYSTEMMAXFILESIZE
  • RUNTIMEMAXFILESIZE
  • MAXRETENTIONSEC
  • MAXFILESEC

これらのパラメータは、アーカイブとしてマークされるログの量を決定します。 アーカイブ済みとしてマークされたログのみをバキュームできるため、保持するログの量を調整することが重要です。

これらのパラメーターを/etc/systemd/journald.confで定義する場合、SYSTEM」で始まるパラメーターを調整する必要があります。 「RUNTIME」パラメータは、ログがメモリ内のファイルシステムに保存されている場合にのみ適用されます。 通常、使用するほとんどのLinuxシステムでは、ログは永続ファイルシステムに保存されます。

KEEPFREE」パラメーターは、 journald が他のユーザーが使用できるように自由に保持しようとするスペースの量を決定し、「 MAXFILESIZE 」パラメーターは、アクティブなジャーナルの最大サイズを決定しますエントリはディスク上で使用できます。 競合がある場合は、2つの間の最小のスペースが優先されます。

すべてのジャーナルファイルの合計ディスク使用量を表示するには、次を使用できます。

journalctl --disk-usage

7. システムログを表示するためのアクセス許可をユーザーに与える

デフォルトでは、特定の権限( root sudo ers、または Wheel )を持つユーザーのみがシステムログを表示できます。 これらの権限がない場合、エラーメッセージが表示されることがあります。

"No journal files were opened due to insufficient permissions."

システム管理を行っているときに、root権限を持たないユーザーが、デバッグのためにすべてのログを表示できるようにしたい場合があります。 グループsystemd-journal adm 、および Wheel / sudo のメンバーは、すべてのジャーナルファイルを読み取ることができます。 一方、グループadmおよびwheel / sudo は、多くの場合、システムに対する他の管理者権限も持っています。

したがって、ユーザーを追加するグループとしてsystemd-journalを使用することをお勧めします。

ユーザーがシステムログを読み取れるようにするには、を実行します。

$ usermod -a -G systemd-journal USER

USERをアクセスを許可するユーザー名に置き換えます。

8. 出力フォーマット

また、ログを別の形式でフォーマットして、保存および分析するために他のシステムに送信することもできます。 -o パラメーターを使用して、これを行うことができます。

$ journalctl -b -u docker -o json

予想どおり、JSON形式のエントリが表示されます。

{
  "__CURSOR": "s=188c4f9b9b9148e8b51e1d83acece38c;i=3262ca;b=1b845a1c4af044128eb82da1b49f8a9e;m=14cfbac;t=5bb02ecf82bd3;x=bdd8df9be3959797",
  "__REALTIME_TIMESTAMP": "1612996123569107",
  "__MONOTONIC_TIMESTAMP": "21822380",
  "_BOOT_ID": "1b845a1c4af044128eb82da1b49f8a9e",
  "PRIORITY": "6",
  "_UID": "0",
  "_GID": "0",
  "_SELINUX_CONTEXT": "unconfined\n",
  "_SYSTEMD_SLICE": "system.slice",
  "_MACHINE_ID": "ed152e13dffc4a0aa8ab86f0b781cd23",
  "_HOSTNAME": "fcivaner-ThinkPad-T480s",
  "SYSLOG_FACILITY": "3",
  "_CAP_EFFECTIVE": "3fffffffff",
  "_TRANSPORT": "stdout",
  "SYSLOG_IDENTIFIER": "dockerd",
  "_COMM": "dockerd",
  "_EXE": "/usr/bin/dockerd",
  "_CMDLINE": "/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock",
  "_SYSTEMD_CGROUP": "/system.slice/docker.service",
  "_SYSTEMD_UNIT": "docker.service",
  "_STREAM_ID": "61ec716173cb4e52bd940795991b3463",
  "_PID": "2002",
  "_SYSTEMD_INVOCATION_ID": "5f3e883264d347c0aec150e82c6b79e5",
  "MESSAGE": "time=\"2021-02-11T01:28:43.568571629+03:00\" level=info msg=\"Docker daemon\" commit=46229ca graphdriver(s)=overlay2 version=20.10.3"
},
...

9. 結論

このチュートリアルでは、 journalctl ツールを使用してログを表示、フィルタリング、およびクリーンアップする方法と、ユーザーがjournalctlを使用してシステムログを表示できるようにシステムを構成する方法を学習しました。