journalctlでログを読む・絞り込む実践テクニック

※本ページには広告(アフィリエイトプログラム等)が含まれます。

さくらのVPSでDebianを運用していると、/var/log/nginx/error.logのような従来型のログファイルだけでなく、systemdが管理する journal にも大量の情報が溜まっている。むしろサービスの起動失敗やOOM Killerの記録など、journal でしか追えない情報の方が多いくらいだ。この記事では journalctl コマンドを使ってログを読む・絞り込むための実践的な使い方をまとめる。

systemd journal とは何か

systemd journal はバイナリ形式でログを一元管理する仕組みで、/run/log/journal(揮発)または /var/log/journal(永続)に保存される。従来の /var/log/syslog や各アプリの個別ログファイルとは違い、サービス単位・時間単位・優先度単位で横断検索できるのが強み。カーネルログ(dmesg相当)もここに集約されるので、原因調査で見る場所が一本化されるのはありがたい。

ただしデフォルトでは揮発ログ(Volatile Storage)になっていることが多く、再起動するとログが消える。これは後述の永続化設定で対処する。

基本操作

まずは素の journalctl。何も付けずに実行すると全ログを古い順にページャ(less)で表示する。

# 全ログをページャで表示
journalctl

# 末尾100行だけ表示(直近の状況確認に便利)
journalctl -n 100

# 追従表示(tail -f 相当、デプロイ直後の監視などに)
journalctl -f

# ページャを使わず標準出力にそのまま流す(パイプで加工したい時)
journalctl --no-pager

-f は本当によく使う。デプロイ直後にこれを流しっぱなしにしてブラウザからアクセスすれば、エラーが出た瞬間にリアルタイムで拾える。

サービス単位で絞り込む

特定のサービスだけ見たい時は -u(unit)オプション。複数指定も可能。

# nginxのログだけ
journalctl -u nginx

# php-fpmのログを追従(PHPのFatal Errorはここに出ることが多い)
journalctl -u php8.3-fpm -f

# 複数サービスをまとめて見る
journalctl -u nginx -u php8.3-fpm

Laravelアプリで500エラーが出た時、まず storage/logs/laravel.log を見て、そこに何もなければ journalctl -u php8.3-fpm でFPM自体が死んでいないか確認する、という流れが定番になっている。

時間で絞り込む

障害調査では「あの時間帯に何が起きたか」を特定するのが重要。--since / --until で範囲指定できる。

# 日付の範囲指定
journalctl --since "2026-01-01" --until "2026-01-02"

# 相対指定(直近1時間)
journalctl --since "1 hour ago"

# 今回の起動分のみ
journalctl -b

# 前回起動分(再起動前のクラッシュ調査に有効)
journalctl -b -1

-b -1 は地味に助かる。サーバーが再起動していた時に「なぜ再起動したのか」を追う際、前回起動の末尾を見ればOOM Killerやカーネルパニックの痕跡が残っていることが多い。

優先度で絞り込む

ログレベル(優先度)でフィルタすれば、大量のinfoログに埋もれずエラーだけ拾える。

# err以上のみ
journalctl -p err

# warning〜errの範囲
journalctl -p warning..err

# カーネルログのみ(dmesg相当)
journalctl -k

優先度は emerg / alert / crit / err / warning / notice / info / debug の順。まず -p err だけ流して異常の有無を一次判定し、必要なら範囲を広げるという使い方が効率的だった。

出力形式を変える

用途に応じて出力フォーマットを切り替えられる。

# タイムスタンプをISO形式で(スクリプト処理・他ログとの突き合わせに)
journalctl -o short-iso

# JSON出力(jqで加工しやすい)
journalctl -o json -u nginx -n 10

# メッセージ本文だけ(余計な情報を削ぎたい時)
journalctl -o cat -u nginx

# grep相当のパターン検索(大文字小文字区別なし)
journalctl -g 'segfault'

-o json は監視ツールに食わせる時や、jqで特定フィールドだけ抜き出したい時に重宝する。-g は正規表現対応なので、複数サービスを横断して特定のエラー文字列を探す時に journalctl -g 'Connection refused' のように使う。

ディスク使用量と掃除

journalが肥大化してディスクを圧迫することがあるので、定期的にサイズを確認する習慣をつけておく。

# 現在のディスク使用量を確認
journalctl --disk-usage

# 7日より古いログを削除
sudo journalctl --vacuum-time=7d

# 合計サイズを500MBまでに削減
sudo journalctl --vacuum-size=500M

思った以上に食っていることがあるので、容量アラートが出た時はまずここを疑う。--vacuum-size は上限まで古いものから削るだけなので、恒久対策としては次の SystemMaxUse で上限を設定しておくのが筋がいい。

永続化とサイズ上限の設定

再起動でログが消えるのは調査上困るので、永続化しておくのが基本。/var/log/journal ディレクトリを作るだけで自動的に永続モードに切り替わる。

sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
sudo systemctl restart systemd-journald

より明示的に設定したい場合は /etc/systemd/journald.conf を編集する。

[Journal]
Storage=persistent
SystemMaxUse=500M

Storage=persistent で永続化を明示し、SystemMaxUse でディスク上限を決めておけば、後から知らないうちにディスクを圧迫される事故を防げる。VPSの限られたディスク容量では500MB程度に抑えておくのが経済的だった。設定後は sudo systemctl restart systemd-journald を忘れずに。

まとめ

journalctl-u でサービスを絞り、--since/-p で時間と優先度を絞り、-f で追従するだけで大抵の障害調査は事足りる。永続化とサイズ上限だけ最初に設定しておけば、あとは困った時にこの記事のオプションを組み合わせれば十分だ。

読んで頂いて有り難うございます!