演習進捗 0 / 4 未完了
⏱ 約 45 分 · journalctl・boot 跨ぎ
Part 3Chapter 02/サーバ運用

journalctl でログを運用者として読む

サービスをわざと壊し、journal から原因を突き止めて直します。さらに電源を落として入れ直し、「落ちる前のログ」をマシンの境界をまたいで読みます。フィルタが強すぎて何も出ないという失敗も、この章で体験します。

教材は登録なしで読めます。実機でコマンドを試す場合のみ、Google ログインで2時間枠の予約が必要です。
所要時間約 45 分
章タイプstandard
前提知識Part 1 Chapter 4(grep でログを読む)/ Part 3 Chapter 1(systemd の概念)
使用機材踏み台 workstation01 + 演習用サーバ learner01(Proxmox 電源操作あり)
関連章前: Chapter 1「systemd でサービスを常駐させる」/ 後: Chapter 3「ユーザ・グループ・権限を設計する」

ログは語る ── 失敗した理由を journal が知っている

深夜 3 時。監視アラートが鳴った。systemctl status myapp を見ると failed になっている。ログはどこにある?

ログの探し方は 2 世代ある
# 昔の方法:ファイルの場所を知っている必要がある
cat /var/log/syslog | grep myapp
cat /var/log/myapp.log

# systemd 時代の方法:サービス名で引く
journalctl -u myapp -n 50 -p err

systemd が普及した現代の Linux では、すべてのサービスのログが journal という 1 か所に集まっています。ファイルを探し回る必要はなく、サービス名・優先度・時刻・何回目の起動かで絞り込めます。

この章の核心は マシンの境界(電源断・再起動)をまたいでログを読むことです。

この章で通す 4 段
① 演習用サービスを作り、正常なログを journal で読む
          ↓
② サービスをわざと壊す(ExecStart を壊す)→ journal で失敗を追う
          ↓
③ 原因を特定して修正 → journal で復旧を確認する
          ↓
④ 電源断(qm stop → qm start)→ journalctl -b -1 で
  「電源が落ちる前のログ」をマシン境界をまたいで読む
この章は Chapter 1 の続きから始める必要はありません。 演習の最初に hello-logger サービスを 1 から作り、壊す → 追う → 直す → 電源イベントまで、すべてこの章の中で完結します。Chapter 1 を受けていない状態でも、そのまま始められます。

この章を終えるとできること

一次調査の 4 動詞を手に覚えます。

$ journalctl
-u hello-logger
-n 10
alive …
① 絞る
サービス単位で
ログを取り出す
-u · -n · -f
ExecStart=
…-BROKEN.sh
Active:
failed
② 壊す
失敗した状態を
自分で作る
sed · restart
$ journalctl
-p err 空!
-n 30
203/EXEC
③ 突き止める
フィルタを外して
原因に辿り着く
-p err · 生ログ
qm stop / start
$ journalctl
-b -1
落ちる前のログ
④ 遡る
電源断の前後を
またいで読む
-b -1 · --list-boots

journal のしくみを解きほぐす

1. journal と /var/log/syslog の違い

かつての Linux は、サービスごとに /var/log/myapp.log を書いたり、syslog が /var/log/syslog にまとめたりしていました。この方式には弱点がありました。

テキストファイル方式の弱点
├── ログの置き場所がサービスごとにバラバラ(/var/log/ を探し回る)
├── ただのテキストなので絞り込みが弱い(優先度・PID・ユニット名で引けない)
└── 再起動をまたぐ検索が難しい(ファイルに「起動の区切り」がない)
journal のしくみ
├── すべてのユニット(サービス・カーネル・ブート)のログを 1 か所に集約
├── バイナリ形式(構造化ログ)→ 優先度・ユニット名・PID・時刻で絞り込める
└── boot ID を記録 → -b -1 で「前回の起動」を名指しできる

journalctl はその閲覧コマンドです。テキストを grep するのとは別の絞り込み方を持ちます。

2. 覚えておきたい 7 つのフラグ

フラグ意味使いどころ
-u <svc>特定サービスのログだけ表示「このサービスに何が起きたか」を見る
-fリアルタイム追従(tail -f 相当)「今まさに起きていること」を追う
--since "TIME"指定時刻以降のログ「あの時刻以降に何があったか」を絞る
-p err優先度フィルタ(err 以上)エラーだけを抽出する(ただし §04 STEP ⑦ の落とし穴あり
-b -1前回ブートのログ電源断・再起動の前のログをまたいで読む
-n <N>末尾 N 行だけ表示直近だけ素早く確認する
--list-bootsブート一覧の表示いくつ前まで遡れるかを確認する

-b は boot(起動の単位)を指定するオプションです。-b 0 が今回の起動(省略時の既定)、-b -1 が 1 つ前の起動、-b -2 が 2 つ前になります。

3. 優先度は 8 段階ある

数字が小さいほど深刻
emerg(0) > alert(1) > crit(2) > err(3) > warning(4) > notice(5) > info(6) > debug(7)

-p err は「err 以上(0〜3)だけを表示」という意味です。-p warning にすると warning 以上(0〜4)が出ます。

ここが後で効いてきます: 「サービスが落ちている」ことと「journal に err で記録される」ことは別の話です。STEP ⑦ で、実際にサービスが落ちているのに -p err では 1 行も出てこない場面に出会います。

4. 「マシン境界をまたぐ」とはどういうことか

/var/log/sysloggrep する方法では、再起動前のログを遡るのに古いファイルを探したり、logrotate の世代を確かめたりする必要がありました。journal は起動ごとに ID を振っているので、1 コマンドで前回の起動を名指しできます。

起動をまたぐ 3 コマンド
# 今回の起動での直近ログ
journalctl -u hello-logger -b 0 -n 1

# 前回の起動(=電源が落ちる前)のログ
journalctl -u hello-logger -b -1

# 何回前まで遡れるか
journalctl --list-boots

実機価値: 「電源が落ちる直前に何が起きていたか」「再起動後にサービスが起き上がったのはいつか」を、マシンの境界をまたいで 1 コマンドで調べられます。これは本当に電源を落とした経験がないと、必要性がぴんと来ない機能です。本章では実際に落として、両側のログを見比べます。

試してみよう:壊して、追って、直して、またいで読む

演習用サービス hello-logger をこの章の中で 1 から作り、わざと失敗させて journal で追跡し、修正して復旧させ、最後に電源イベントをまたいでログを読みます。

項目
出発地点踏み台 workstation01
演習対象learner01(サービス作成・journalctl 操作)
Proxmox 操作Proxmox ホスト(<Proxmox管理IP>
ゲスト操作ユーザーops(NOPASSWD sudo)
所要時間約 40 分(10 ステップ)
失敗しても安全です: 作るのは /usr/local/bin/hello-logger.sh/etc/systemd/system/hello-logger.service の 2 ファイルだけです。STEP ⑩ のクリーンアップを上から順に実行すれば、どの段階からでもクリーン状態に戻せます。VMID の確認方法: Proxmox ホストで qm list | grep learner01 を実行すると、左端の数字が VMID です。以降 <VMID> と記します。

STEP 01 · 接続して、クリーン状態を確認する

bash · workstation01 → learner01
# workstation01 から learner01 へ接続
ssh ops@learner01

# 前セッションの残骸チェック
systemctl status hello-logger

Unit hello-logger.service could not be found. と出ればクリーン状態です。activefailed が出る場合は前回の演習が途中で終わった名残なので、先に STEP ⑩「章末クリーンアップ」を実行してから STEP ① に戻ってください。

STEP 02 · journal が永続保存されているか確認する

この章の核心である journalctl -b -1(STEP ⑨)は、journal が永続保存されていないと動きません。先に確認し、無効なら有効化します。

bash · learner01
# 永続保存されているか確認。無ければ有効化する
ls /var/log/journal/ 2>/dev/null || (sudo mkdir -p /var/log/journal && sudo systemctl restart systemd-journald)

# 起動の履歴を確認
journalctl --list-boots
出力例
[machine-id]
 -1 [boot-id] Sun 2026-07-26 17:27:22 JST Sun 2026-07-26 22:10:14 JST
  0 [boot-id] Tue 2026-07-28 09:35:28 JST Tue 2026-07-28 09:55:22 JST

/var/log/journal/ が存在し、--list-boots に 1 行以上出れば準備完了です。No such file or directory が出た場合は || の後ろが自動で走り、systemd-journald が再起動されます。

なぜ先に確認するか: /var/log/journal/ が無い環境では、journal は /run/log/journal/(メモリ上)に保存されます。メモリ上ということは、電源が落ちれば消えるということです。この章の主役 -b -1 は前回のログを読む機能なので、先に「消えない場所に書く」設定を担保しておきます。

この設定は章末で戻しません: /var/log/journal/ は Part 3 の他の章でも使うため、クリーンアップの対象外です。

STEP 03 · 演習用サービスを作る

Chapter 1 を受けたかどうかに関係なく、ここで 1 から作ります。

bash · learner01
# スクリプトを作成
sudo tee /usr/local/bin/hello-logger.sh << 'EOF'
#!/bin/bash
while true; do
    echo "$(date '+%Y-%m-%d %T') [hello-logger] alive"
    sleep 5
done
EOF

sudo chmod 755 /usr/local/bin/hello-logger.sh
bash · learner01
# ユニットファイルを作成
sudo tee /etc/systemd/system/hello-logger.service << 'EOF'
[Unit]
Description=Hello Logger - 演習用タイムスタンプ記録サービス
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/hello-logger.sh
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now hello-logger
systemctl is-active hello-logger
期待される出力
active

StandardOutput=journal と書いてあるのがポイントです。スクリプトが echo した内容は、画面ではなく journal に流れ込みます。30 秒ほど動かしてから次に進むと、読めるログが溜まっています。

STEP 04 · 正常なログを読む

bash · learner01
# このサービスのログを末尾 10 行だけ
journalctl -u hello-logger -n 10
期待される出力
7月 28 09:50:37 learner01 hello-logger.sh[2826]: 2026-07-28 09:50:37 [hello-logger] alive
7月 28 09:50:42 learner01 hello-logger.sh[2826]: 2026-07-28 09:50:42 [hello-logger] alive
7月 28 09:50:47 learner01 hello-logger.sh[2826]: 2026-07-28 09:50:47 [hello-logger] alive
7月 28 09:50:52 learner01 hello-logger.sh[2826]: 2026-07-28 09:50:52 [hello-logger] alive

1 行の形は 月 日 時刻 ホスト名 ユニット名[PID]: メッセージ です。時刻・ホスト名・ユニット名・PID が別々の項目として記録されているので、あとから好きな条件で絞り込めます。ここがテキストファイルとの違いです。

bash · learner01
# リアルタイムに追いかける
journalctl -u hello-logger -f

5 秒ごとに行が増えていくのを確認したら、Ctrl + C で止めてください。

bash · learner01
# 直近 5 分だけに絞る
journalctl -u hello-logger --since "5 minutes ago"

ページャの操作: journalctl は既定で less が開きます。スクロールは方向キー、終了は q です。パイプで grep に渡したいときは --no-pager を付けてください。

STEP 05 · 優先度で絞ってみる(正常時)

bash · learner01
# err(3)以上の優先度だけを表示
journalctl -u hello-logger -p err
期待される出力
-- No entries --

いまは正常に動いているので、エラーはありません。この「空っぽ」の見え方を覚えておいてください。STEP ⑦ で、サービスが壊れているのにまったく同じ表示に出会います。

STEP 06 · 壊す ── 起動できないサービスにする

ExecStart= を存在しないパスに書き換えて、サービスを起動不能にします。

bash · learner01
# ExecStart のパスを壊す
sudo sed -i 's|ExecStart=/usr/local/bin/hello-logger.sh|ExecStart=/usr/local/bin/hello-logger-BROKEN.sh|' \
    /etc/systemd/system/hello-logger.service

# 変更を反映して再起動
sudo systemctl daemon-reload
sudo systemctl restart hello-logger

systemctl status hello-logger
期待される出力
● hello-logger.service - Hello Logger - 演習用タイムスタンプ記録サービス
     Loaded: loaded (/etc/systemd/system/hello-logger.service; enabled; preset: enabled)
     Active: activating (auto-restart) (Result: exit-code) since Tue 2026-07-28 09:51:09 JST; 2s ago
    Process: 3611 ExecStart=/usr/local/bin/hello-logger-BROKEN.sh (code=exited, status=203/EXEC)
   Main PID: 3611 (code=exited, status=203/EXEC)
7月 28 09:51:09 learner01 systemd[1]: hello-logger.service: Main process exited, code=exited, status=203/EXEC
7月 28 09:51:09 learner01 systemd[1]: hello-logger.service: Failed with result 'exit-code'.

壊れました。Active:activating (auto-restart) になっているのは、Restart=on-failure が 5 秒おきに再挑戦し続けているからです。失敗しては再起動する、を延々と繰り返している状態です。

STEP 07 · 追う ── 優先度フィルタの落とし穴

失敗の原因を journal で探します。まず、いかにも正しそうな方法から試します。

bash · learner01
# エラーだけ見れば分かるはず……?
journalctl -u hello-logger -p err -n 20
実際の出力
-- No entries --

何も出ません。サービスは確実に壊れていて、いまも 5 秒おきに失敗し続けているのに、です。

なぜ空になるのか: systemd がユニットの失敗を報告する行は、err(3)ではなく notice(5)や warning(4)で記録されています。「サービスが落ちている」ことと「journal に err で記録される」ことは別なのです。しかも実測では、-p warning まで下げても核心の 203/EXEC の行は出てきません。優先度フィルタは万能ではありません。

調査ではフィルタを外すのが確実です。

bash · learner01
# 優先度を指定せず、全レベルで直近 30 行
journalctl -u hello-logger -n 30
期待される出力
7月 28 09:51:30 learner01 systemd[1]: hello-logger.service: Scheduled restart job, restart counter is at 5.
7月 28 09:51:30 learner01 systemd[1]: Started hello-logger.service - Hello Logger - 演習用タイムスタンプ記録サービス.
7月 28 09:51:30 learner01 systemd[1]: hello-logger.service: Main process exited, code=exited, status=203/EXEC
7月 28 09:51:30 learner01 systemd[1]: hello-logger.service: Failed with result 'exit-code'.
(中略)
7月 28 09:52:01 learner01 systemd[1]: hello-logger.service: Scheduled restart job, restart counter is at 11.
7月 28 09:52:01 learner01 systemd[1]: Started hello-logger.service - Hello Logger - 演習用タイムスタンプ記録サービス.
7月 28 09:52:01 learner01 systemd[1]: hello-logger.service: Main process exited, code=exited, status=203/EXEC
7月 28 09:52:01 learner01 systemd[1]: hello-logger.service: Failed with result 'exit-code'.

今度は出ました。読み取るべきは status=203/EXEC です。203/EXEC は「指定された実行ファイルを起動できなかった」という意味で、パスの間違いか実行権限の欠落で起こります。これが根本原因です。

restart counter is at 5at 11 と数字が増えているのは、その間も失敗し続けていた証拠です。調査中も時計は動いています。

この章で一番持ち帰ってほしいこと: 「エラーを見る」つもりで -p err を打ち、空だったからといって「問題ない」と判断してはいけません。フィルタが強すぎて見えていないだけかもしれません。困ったら、まずフィルタを外す。

STEP 08 · 直す ── 復旧を journal で確認する

bash · learner01
# ExecStart を正しいパスに戻す
sudo sed -i 's|ExecStart=/usr/local/bin/hello-logger-BROKEN.sh|ExecStart=/usr/local/bin/hello-logger.sh|' \
    /etc/systemd/system/hello-logger.service

sudo systemctl daemon-reload
sudo systemctl restart hello-logger
systemctl is-active hello-logger
期待される出力
active
bash · learner01
# 失敗から復旧までの流れが 1 か所に残っている
journalctl -u hello-logger -n 10
期待される出力
7月 28 09:54:59 learner01 systemd[1]: hello-logger.service: Main process exited, code=exited, status=203/EXEC
7月 28 09:54:59 learner01 systemd[1]: hello-logger.service: Failed with result 'exit-code'.
7月 28 09:55:02 learner01 systemd[1]: Stopped hello-logger.service - Hello Logger - 演習用タイムスタンプ記録サービス.
7月 28 09:55:02 learner01 systemd[1]: Started hello-logger.service - Hello Logger - 演習用タイムスタンプ記録サービス.
7月 28 09:55:02 learner01 hello-logger.sh[4727]: 2026-07-28 09:55:02 [hello-logger] alive
7月 28 09:55:07 learner01 hello-logger.sh[4727]: 2026-07-28 09:55:07 [hello-logger] alive

「失敗 → 繰り返し → 修正後に正常起動」という一連の流れが、時系列で 1 か所に残っています。これが障害対応の証跡になります。「いつ壊れて、いつ直ったか」を後から人に説明できる形です。

復旧したと判定する条件: systemctl is-active hello-loggeractive を返し、かつ journalctl -u hello-logger -n 10[hello-logger] alive の行が見えること。

STEP 09 · またぐ ── 電源断の前後を読み比べる

この章の核心です。まず現在の起動履歴を控えます。

bash · learner01
journalctl --list-boots
出力例(電源断の前)
 -2 [boot-id] Sun 2026-07-19 11:51:46 JST Sun 2026-07-19 11:56:11 JST
 -1 [boot-id] Sun 2026-07-26 17:27:22 JST Sun 2026-07-26 22:10:14 JST
  0 [boot-id] Tue 2026-07-28 09:35:28 JST Tue 2026-07-28 09:55:22 JST

0 の行が「今の起動」です。この後の電源断で、この行が -1 に押し下がります

workstation01別のターミナルを開いて、Proxmox ホストから電源を落とします。

bash · Proxmox ホスト
# 別ターミナルで Proxmox ホストに接続
ssh ops@<Proxmox管理IP>

qm list | grep learner01     # VMID を確認
qm stop <VMID>              # 電源断相当
qm status <VMID>            # stopped を確認
qm start <VMID>             # 再投入

およそ 20〜30 秒待ってから learner01 に再接続し、起動履歴を見直します。

bash · workstation01 → learner01
ssh ops@learner01
journalctl --list-boots
出力例(電源断の後)
 -2 [boot-id] Sun 2026-07-26 17:27:22 JST Sun 2026-07-26 22:10:14 JST
 -1 [boot-id] Tue 2026-07-28 09:35:28 JST Tue 2026-07-28 09:55:37 JST
  0 [boot-id] Tue 2026-07-28 09:56:00 JST Tue 2026-07-28 09:58:36 JST

さっき 0 だった行が -1 に移動しました。行がひとつずつ押し下がるのが、電源が 1 回落ちたということの journal 上の意味です。

bash · learner01
# 電源が落ちる前のログ
journalctl -u hello-logger -b -1
期待される出力(前回ブート)
7月 28 09:55:02 learner01 systemd[1]: Started hello-logger.service - Hello Logger - 演習用タイムスタンプ記録サービス.
7月 28 09:55:02 learner01 hello-logger.sh[4727]: 2026-07-28 09:55:02 [hello-logger] alive
7月 28 09:55:07 learner01 hello-logger.sh[4727]: 2026-07-28 09:55:07 [hello-logger] alive
(中略)
7月 28 09:55:37 learner01 hello-logger.sh[4727]: 2026-07-28 09:55:37 [hello-logger] alive
bash · learner01
# 電源を入れ直した後のログ
journalctl -u hello-logger -b 0
期待される出力(今回ブート)
7月 28 09:57:31 learner01 hello-logger.sh[1080]: 2026-07-28 09:57:31 [hello-logger] alive
7月 28 09:57:36 learner01 hello-logger.sh[1080]: 2026-07-28 09:57:36 [hello-logger] alive
(中略)
7月 28 09:58:41 learner01 hello-logger.sh[1080]: 2026-07-28 09:58:41 [hello-logger] alive

2 つの出力を見比べてください。ログは 09:55:37 でぷつりと途切れ、09:57:31 から再開しています。この空白が電源の落ちていた時間です。PID も 4727 から 1080 に変わっており、別の OS セッションであることが数字にも出ています。

本番での使い方: サーバが予期せず再起動していたとき、journalctl -b -1 -p err で前回の終わり際のエラーを絞り込むのが一次調査の定石です。ただし STEP ⑦ で見たとおり、-p err で空でも「異常なし」とは限りません。空だったらフィルタを外して読み直してください。

STEP 10 · 章末クリーンアップ

bash · learner01
# 停止して自動起動も解除
sudo systemctl disable --now hello-logger

# ファイルを削除
sudo rm /etc/systemd/system/hello-logger.service
sudo rm /usr/local/bin/hello-logger.sh

# 反映して確認
sudo systemctl daemon-reload
systemctl status hello-logger

Unit hello-logger.service could not be found. と出れば完了です。これはエラーではなく「もう無い」という意味です。

/var/log/journal/ は消しません: STEP ② で有効にした journal の永続保存は、Part 3 の他の章でも使うため残します。

クリーンアップ完了の確認
確認項目期待値
systemctl status hello-loggerUnit hello-logger.service could not be found.
/etc/systemd/system/hello-logger.service存在しない
/usr/local/bin/hello-logger.sh存在しない
演習中の -p err(STEP ⑦)-- No entries -- になることを確認済み(=これが正しい)
演習中の -n 30(STEP ⑦)status=203/EXEC を確認済み
演習中の -b -1(STEP ⑨)電源断前のログを確認済み
/var/log/journal/残したまま(消さない)

詰まったら

ハマりポイント

STEP ⑦ で -p err が空になる

それが正しい結果です。この章はその「空」をわざと見せるために作られています。

systemd がユニットの失敗を書く行の優先度は、203/EXEC の行が notice(5)、Failed with result の行が warning(4)です。どちらも err(3)より低いため、-p err の網には掛かりません。実測では -p warning まで下げても核心の 203/EXEC 行は出ません

優先度の指定そのものを外して journalctl -u hello-logger -n 30 で確認してください。

STEP ⑨ で journalctl -b -1 が空になる

まず journalctl --list-boots-1 の行が存在するかを確認してください。

行が無い場合: STEP ② の永続保存が効いていません。ls /var/log/journal/ でディレクトリの存在を確認し、無ければ作り直して sudo systemctl restart systemd-journald を実行します。ただし、永続化する前のブートのログは戻ってきません(メモリ上にあったものは電源断で消えています)。その場合はもう一度 qm stopqm start を行えば、次からは -b -1 で読めます。

行はあるのに空の場合: そのブート中に hello-logger が動いていなかった可能性があります。-u を外した journalctl -b -1 -n 30 で、そのブート自体のログがあるかを確かめてください。

STEP ⑨ で SSH がつながらない

Connection refused: VM の起動がまだ終わっていません。qm start から 20〜30 秒待って再試行してください。

Connection timed out during banner exchange: ping も通りポート 22 も開いているのに出ることがあります。sshd がまだ応答を返し始めていない状態です。1〜2 分待ってから再試行してください。ポートが開いていることと、応答が始まっていることは別です。

上記以外の詰まりと対処を一覧にまとめます。

起きたこと対処
--list-boots が空、または表示されないsudo systemctl status systemd-journald で journald の状態を確認し、sudo systemctl restart systemd-journald を実行してから再試行
journalctl -u hello-logger-- No entries --サービスが起動した直後で、まだログが無い。10〜15 秒待って再実行。それでも空なら systemctl is-active で動いているか確認
sed の後の restartUnit not founddaemon-reload を忘れている。sudo systemctl daemon-reload を実行してから再試行
⑧ 修正したのに failed が続くdaemon-reload を実行したか確認。restart だけではユニットファイルの変更が反映されない
ページャから抜けられないq で終了。そもそも開きたくない場合は --no-pager を付ける

AI に相談

AI journalctl の詰まりを自由に質問できます
この章の journalctl・優先度・boot 単位ログを前提に、インフラの基礎をやさしく答えます

修了確認

ログを読む技術と、フィルタの落とし穴を確認します。

問 1 · -b -1 の意味と使いどころ

journalctl -u hello-logger -b -1-b -1 は何を意味しますか? また、このオプションが特に役立つのはどんな場面ですか?

解答を見る

-b は boot(起動の単位)を指定するオプションです。-b 0 が今回の起動(省略時の既定)、-b -1 が 1 つ前の起動を指します。したがってこのコマンドは「前回の OS 起動中に、このサービスが出力したログ」を表示します。

役立つ場面:

  • サーバが予期せず再起動した後に「落ちる直前に何が起きていたか」を調べる
  • 電源断から復帰した後に、前回のエラーを遡る
  • 夜間に起きた障害を翌朝に調査する(-b -1 で昨晩のログを読む)

ただし、これが使えるのは journal が永続保存されている場合だけです(/var/log/journal/ が存在すること)。メモリ上(/run/log/journal/)に保存されている環境では、電源が落ちた時点でログも消えます。STEP ② で先に確認したのはこのためです。

問 2 · failed のときの一次調査

サービスが Active: failed になっているとき、どんな順序で調べますか? 使うコマンドを含めて説明してください。また、journalctl -p err が空だったとき、どう解釈すべきですか?

解答を見る
一次調査の順序
# 1. 概要をつかむ(Active の状態・直近数行・終了コード)
systemctl status <svc>

# 2. フィルタを掛けずに直近のログを読む(← ここが要)
journalctl -u <svc> -n 50

# 3. 時刻が分かっているなら絞り込む
journalctl -u <svc> --since "10 minutes ago"

-p err が空だったときの解釈: 「異常なし」ではありません。そのフィルタでは見えていない、というだけです。systemd はユニットの失敗を noticewarning で記録するため、-p err の網から漏れます。空だったら優先度の指定を外して読み直してください。

よくある原因と対処:

ログに出るもの意味対処
status=203/EXEC指定した実行ファイルを起動できなかったパスの誤りか実行権限の欠落。ExecStart= を直すか chmod 755
Permission denied実行権限がないsudo chmod 755 <path> の後に restart
0 以外の終了コードスクリプト自体が異常終了したスクリプトの中身を確認して修正

いずれの場合も、ユニットファイルを直したら daemon-reloadrestart の順です。修正後は systemctl is-active と journal の両方で確認します。

段階ヒント(問 1・問 2 共通)

段階ヒント 1 段目:出ないときは、まず絞りすぎを疑う

journalctl で何も出ないときは、フィルタが厳しすぎることがほとんどです。まず -u <svc> だけで全体を見て、そこから -p--since を足していく順番で進めてください。逆順(最初から絞る)で始めると、この章の STEP ⑦ と同じ落とし穴にはまります。

段階ヒント 2 段目:用途別のコマンド一覧
ログの読み方
journalctl -u hello-logger                        # 全体
journalctl -u hello-logger -n 20                  # 末尾 20 行
journalctl -u hello-logger -f                     # 追従(Ctrl+C で止める)
journalctl -u hello-logger --since "5 minutes ago" # 時刻で絞る
journalctl -u hello-logger -p err                 # err 以上(空でも異常なしとは限らない)
起動をまたぐ
journalctl --list-boots            # 何回前まで遡れるか
journalctl -u hello-logger -b -1   # 前回の起動
journalctl -u hello-logger -b 0    # 今回の起動

よくある落とし穴:

  • 既定でページャ(less)が開く。終了は q、使いたくなければ --no-pager
  • -b -1 には journal の永続保存が必要(STEP ② で担保済み)
  • -p err が空でも「異常なし」ではない(STEP ⑦)
答えを見る(フルコマンド列)
全手順(learner01 + Proxmox ホスト)
# ── STEP② journal 永続化 ──
ls /var/log/journal/ 2>/dev/null || (sudo mkdir -p /var/log/journal && sudo systemctl restart systemd-journald)
journalctl --list-boots

# ── STEP③ サービス作成後 ──
sudo systemctl daemon-reload
sudo systemctl enable --now hello-logger
systemctl is-active hello-logger    # active

# ── STEP④⑤ 読む ──
journalctl -u hello-logger -n 10
journalctl -u hello-logger --since "5 minutes ago"
journalctl -u hello-logger -p err    # 正常時は -- No entries --

# ── STEP⑥ 壊す ──
sudo sed -i 's|ExecStart=/usr/local/bin/hello-logger.sh|ExecStart=/usr/local/bin/hello-logger-BROKEN.sh|' \
    /etc/systemd/system/hello-logger.service
sudo systemctl daemon-reload
sudo systemctl restart hello-logger
systemctl status hello-logger        # 203/EXEC で失敗

# ── STEP⑦ 追う ──
journalctl -u hello-logger -p err -n 20  # -- No entries --(これが正しい)
journalctl -u hello-logger -n 30          # status=203/EXEC が見える

# ── STEP⑧ 直す ──
sudo sed -i 's|ExecStart=/usr/local/bin/hello-logger-BROKEN.sh|ExecStart=/usr/local/bin/hello-logger.sh|' \
    /etc/systemd/system/hello-logger.service
sudo systemctl daemon-reload
sudo systemctl restart hello-logger
systemctl is-active hello-logger      # active(復旧)

# ── STEP⑨ Proxmox ホスト(別ターミナル)──
qm stop <VMID>
qm start <VMID>

# ── STEP⑨ learner01(20〜30 秒後)──
journalctl --list-boots
journalctl -u hello-logger -b -1     # 電源断前
journalctl -u hello-logger -b 0      # 電源投入後

# ── STEP⑩ クリーンアップ ──
sudo systemctl disable --now hello-logger
sudo rm /etc/systemd/system/hello-logger.service
sudo rm /usr/local/bin/hello-logger.sh
sudo systemctl daemon-reload

このフローで覚えること:

  • 調査は「絞らずに全体 → 徐々に絞る」の順。逆順は見落とす
  • -p err が空でも異常なしとは限らない。フィルタを外して読み直す
  • -b -1 で前回の起動を読むには、journal の永続保存が要る

次の章へ

ログを追う技術で、インシデントの一次調査ができるようになりました。次は視点を変えて、そのサーバに誰がアクセスできて、誰が何をできるのかを設計します。ユーザを作り、グループでまとめ、共有ディレクトリの権限を決める ── さらに踏み台から別のユーザで learner01 にログインし、権限の境界を自分の目で確かめます

Chapter 3: ユーザ・グループ・権限を設計する:
  • ユーザとグループを作り、共有ディレクトリの権限を設計する
  • 「読めるが書けない」「書けるが消せない」を権限で作り分ける
  • 別ユーザで実際にログインし、境界を越えられないことを確かめる

もっと知りたい方へ