journalctlを理解する
連載ナビ
この連載は「Linuxを使えるようになる」ではなく、「Linuxがどう動いているのか」を理解するための実践シリーズです。
今回は Linuxを理解する 〜 LFSで学ぶLinux内部構造 〜 の Part 5 / 第5回として、仕組みのつながりを意識しながら学びます。
- 前回: daemonとは何か
- 次回: Linuxネットワーク基礎
—
journalctlは「journaldが一元収集したログを検索するツール」
前回の宿題、「端末を持たないdaemonの出力はどこへ行くのか」から始めます。
結論から言うと、systemd環境ではsystemd-journaldというdaemonが、全サービスの標準出力・標準エラー出力、syslog経由のログ、カーネルのログまでを一元的に回収し、構造化された形式で保存しています。その保存先を検索・閲覧するコマンドが journalctl です。
各サービスのstdout/stderr ─┐
syslog経由のメッセージ ─┼─> systemd-journald ─> ジャーナルファイル ─> journalctl で閲覧
カーネルログ(dmesg相当) ─┘
保存先はジャーナル専用のバイナリ形式で、場所は /run/log/journal/(メモリ上・再起動で消える)または /var/log/journal/(ディスク上・永続)です。バイナリなので cat では読めませんが、その代わり各レコードにunit名・PID・優先度・ブートIDといったメタデータが付いており、これがjournalctlの強力な絞り込みを支えています。
「サービスごとにバラバラのテキストファイル」では調査が遅いから
なぜ従来の /var/log/ 以下のテキストログではなく、journaldという仕組みが作られたのか。理由は、従来方式には調査を遅くする構造的な問題があったからです。
- 置き場所とフォーマットがバラバラ: nginxは
/var/log/nginx/error.log、認証は/var/log/auth.log、それ以外は/var/log/syslog……とサービスごとに場所が違い、タイムスタンプの書式すら揃っていません。複数サービスにまたがる障害では、ファイルを行き来しながら時刻を突き合わせる必要がありました - メタデータがない: テキスト行には「どのunitが出したか」「そのときのブートは何回目か」という情報がなく、
grepの工夫でカバーするしかありませんでした - 標準出力が捨てられる: 前回見たとおりdaemonは端末を持たないため、素朴に起動すると標準出力への出力は行き場を失います。サービスごとにログファイル出力の実装が必要でした
journaldはこれらを一挙に解決します。サービスは標準出力に書くだけでよく(12-factor appの「ログはstdoutへ」と同じ思想です)、回収・メタデータ付与・保存はjournaldが担い、閲覧はjournalctlの統一されたインターフェースで行えます。
絞り込みオプションを5つ覚えれば実戦で使える
journalctlは引数なしで実行すると全ログが古い順に出て圧倒されます。実用上は「絞り込んで見る」が基本で、次の5つを覚えれば日常調査の大半をカバーできます。
# 1. -u : unit(サービス)で絞る
journalctl -u nginx
# 2. -b : ブート単位で絞る(-b は今回起動分、-b -1 は前回起動分)
journalctl -b
journalctl -b -1
# 3. --since / --until : 時刻で絞る
journalctl --since "2026-08-22 09:00" --until "2026-08-22 10:00"
journalctl --since "1 hour ago"
# 4. -p : 優先度で絞る(err で「エラー以上」= err, crit, alert, emerg)
journalctl -p err -b
# 5. -f : 流れてくるログを追いかける(tail -f 相当)
journalctl -u nginx -f
オプションは組み合わせられます。「今回の起動で、nginxが出したエラー以上のログ」なら journalctl -b -u nginx -p err です。ほかに、カーネルメッセージだけを見る -k(dmesg 相当)、末尾から表示する -e、行数を絞る -n 50 も頻出です。
特に -b -1(前回起動分)は覚える価値があります。「サーバーが突然再起動した。直前に何が起きたのか」という調査では、今回のログではなく前回のブートの末尾を見る必要があるからです。
journalctl -b -1 -e
サービス起動失敗を調査する、実戦の流れ
Part 5の総仕上げとして、これまでの回をつなげた調査フローを見ます。たとえば systemctl start nginx が失敗したとします。
$ sudo systemctl start nginx
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xeu nginx.service" for details.
エラーメッセージ自体が次の一手を教えてくれています。指示どおりに進めます。
# 手順1: statusで状態と直近ログの要約を見る
systemctl status nginx
# 手順2: journalctlで該当unitのログを詳しく見る
# -x は説明文の追加、-e は末尾へジャンプ、-u はunit指定
journalctl -xeu nginx.service
ログにたとえば nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use) とあれば、ポート80が既に使われていることが原因だと特定できます。「systemctlで状態確認 → journalctlで該当unitのログ確認」という2段階は、systemd環境の障害初動の定石です。
もう1つ、実務で必ず確認したいのがログの永続化設定です。/var/log/journal/ ディレクトリが存在しない環境では、ジャーナルは /run/log/journal/(tmpfs上)にしか書かれず、再起動するとログが消えます。その場合 journalctl -b -1 は「Specifying boot ID or boot offset has no effect, no persistent journal was found」という趣旨のメッセージを出して前回分を表示できません。永続化するには次のようにします(設定は /etc/systemd/journald.conf の Storage= でも制御できます)。
sudo mkdir -p /var/log/journal
sudo systemctl restart systemd-journald
ビルドから起動、常駐、ログまでが1本につながった
journalctlは、journaldが一元収集した構造化ログを、unit・ブート・時刻・優先度で絞り込んで読むツールである——これが今回のポイントです。前回の自作daemonの echo の出力も、journalctl -u hello で確認できます。
これでPart 5は完結です。カーネルを自分でビルドし(第1回)、initramfsが本物のルートへ橋渡しし(第2回)、systemdがPID 1としてサービスを起動・監視し(第3回)、その実体であるdaemonが常駐し(第4回)、その出力をjournalctlで追跡する(今回)——起動からログ調査までが1本の線になりました。次回からのPart 6では、動き出したシステムの外側、ネットワークの世界に進みます。
図解テキスト
service logs (stdout/stderr) ─┐
syslog ─┼─> journald ─> /var/log/journal/ (永続)
kernel log ─┘ /run/log/journal/ (揮発)
└─> journalctl -u/-b/--since/-p/-f
この回で実行するコマンド
上から順番に実行すれば、この回の内容を体験できます。
まずはそのままコピペして実行し、次に1行ずつ意味を確認してください。
# 今回の起動分のログを先頭から確認
journalctl -b | head -n 80
# sshdのログをunit指定で確認(環境によりunit名は ssh の場合あり)
journalctl -u sshd -b 2>/dev/null | tail -n 80 || journalctl -u ssh -b 2>/dev/null | tail -n 80 || true
# 今回の起動での「エラー以上」だけを確認
journalctl -p err -b --no-pager | tail -n 40
# ログが永続化されているか確認(ディレクトリがなければ揮発運用)
ls /var/log/journal/ 2>/dev/null || echo "persistent journal なし(/run/log/journal のみ)"
ハンズオン手順
1. ターミナルを開いて、上のコマンドを1行ずつ実行する
2. journalctl -p err -b で見つけたエラーを1つ選び、-u でそのunitに絞って前後の文脈を読む
3. /var/log/journal/ の有無を確認し、自分の環境のログが再起動後も残るか判断する
4. エラーが出たら、そのエラーメッセージをそのまま残す
チェックポイント
- コマンドが最後まで実行できた
-u-b--since-p-fの5オプションの意味を言える- サービス起動失敗時の初動2手順(
systemctl status→journalctl -xeu)を説明できる - 次の回に進む前に、分からない単語を1つ調べた
今回理解できたこと
- journalctlは起動単位・サービス単位で追跡できる(
-bと-uの組み合わせが基本) - ログ調査の再現性が上がる(メタデータ付きの一元管理で、grep頼みの調査から卒業できる)
- 永続化には
/var/log/journal/が必要で、なければ再起動でログが消える