1. はじめに
サービスが起動しないときは、再起動を繰り返す前に、状態とログを確認しましょう。本記事ではRHEL10を対象に、systemctlとjournalctlで原因を絞り込む順序を説明します。
この記事の主手順は確認操作のみです。対象サービス名は環境に合わせて置き換えてください。blog-demo-fail.serviceは撮影用に用意した独立した検証サービスの名前であり、RHEL標準のサービスではありません。
検証環境はRHEL 10.2(Coughlan)、systemd-257-23.el10_2.2.x86_64です。専用検証環境で一時サービスから /usr/bin/false を実行し、意図的な失敗を再現しました。実際のアプリケーション障害の原因がすべて同じという意味ではありません。
確認コマンドは、サービス状態や設定を変更しません。画像はroot権限で取得しています。利用者の権限によって閲覧できるログが異なる場合があります。
2. 起動に失敗したサービスを確認する
systemctl --failed --type=service --no-pager
一覧のUNITでサービス名を確認します。failedは起動失敗や異常終了などを示しますが、原因までは分かりません。一覧が空でも、アプリケーションの正常動作が保証されるわけではありません。

画像のUNITは blog-demo-fail.service、ACTIVEとSUBは failed です。これで調査対象を特定します。
3. systemctl statusで状態と直近のメッセージを見る
systemctl status blog-demo-fail.service --no-pager -l
Loaded、Active、実行プロセスの終了情報、末尾のメッセージを確認します。-lは省略表示を減らし、--no-pagerはページャーを使わず表示する指定です。
inactiveは停止状態であり、それだけで異常とは限りません。not-foundなら名前や導入状況、maskedなら意図的な起動禁止の有無を確認します。enabledは自動起動の設定で、現在動作中という意味ではありません。
対象が停止・失敗状態の場合、statusコマンド自体も0以外の終了コードを返すことがあります。それだけで確認コマンドの故障とは判断しません。

今回の結果は Active: failed (Result: exit-code)、ExecStart=/usr/bin/false、status=1/FAILURE でした。Loadedには /run/systemd/transient/ 配下の定義が表示され、Transient: yes と確認できます。
4. journalctlで対象サービスのログを読む
journalctl -u blog-demo-fail.service -b -n 50 --no-pager
-uは対象unit、-bは今回のOS起動以降、-n 50は末尾50件の指定です。失敗時刻の前後を読み、エラーメッセージだけでなく、その直前の処理も確認します。50件に失敗時刻が含まれなければ、取得件数や期間を広げます。
設定の読み込み失敗、ファイルへのアクセス拒否、使用中のポートなど、表示された根拠から調査先を絞ります。エラーだけに絞ると前後関係を見落とす場合があります。アプリケーション独自のログファイルへ記録される情報もあります。
ログが見つからないときは、サービス名、発生時刻、ログ閲覧権限を確認してください。前回起動時のログは、保存設定などによって残っていない場合があります。

画像では、起動開始に続いて Main process exited, code=exited, status=1/FAILURE、Failed with result 'exit-code' と記録されています。今回は /usr/bin/false の意図的な失敗であり、設定ファイルの不備が確認された例ではありません。
5. 終了状態とサービス定義を確認する
systemctl show blog-demo-fail.service -p LoadState -p ActiveState -p SubState -p Result -p ExecMainCode -p ExecMainStatus
Resultと終了情報を、statusやログと照合します。例えば終了ステータス1だけでは原因を特定できません。実行されたプログラムの仕様とログを合わせて判断します。

今回の表示は Result=exit-code、ExecMainCode=1、ExecMainStatus=1、LoadState=loaded、ActiveState=failed、SubState=failed でした。終了ステータスは ExecMainStatus の値です。ExecMainCodeとは別の項目であり、両者を混同しないでください。
systemctl cat blog-demo-fail.service --no-pager
サービス定義と追加設定を確認します。ExecStartに書かれた実行対象や引数をログと照合します。この表示は定義ファイルの内容であり、編集後に読み込み直していない場合など、systemdが現在保持している設定と一致しないことがあります。

画像では Type=oneshot と ExecStart="/usr/bin/false" を確認できます。直前の空の ExecStart= だけを見て、実行対象がないとは判断しません。今回の一時サービス定義は自動生成されたものなので、直接編集しません。
【注意】ログや定義には、認証情報、社内ホスト名、顧客情報が含まれる場合があります。画面を公開・共有する前に確認してください。
6. 原因を絞ってから対処する
サービス名が違うなら正しい名前を調べ、設定エラーなら指摘されたファイルや行を確認します。権限やポート競合も、メッセージと実際の設定を照合してから対処します。
原因が分からないままサービスを再起動したり、firewalldやSELinuxを無効化したりしないでください。変更が必要な場合は、影響範囲、バックアップ、復旧経路、作業時間を先に決めます。SSHやNetworkManagerの操作は管理接続を切断する可能性があります。
7. 関連記事とまとめ
journalctlの表示方法を広げたい場合は、journalctlコマンドの解説も参考にしてください。
確認する順序は「失敗一覧 → 状態 → ログ → 終了情報・定義」です。まず証拠を残し、原因に合わせて次の調査を選びましょう。サービス起動の失敗と、ネットワーク越しに接続できない問題は、分けて考えることが大切です。
参考: systemctl公式マニュアル、journalctl公式マニュアル。一般的なオプション説明は公式資料を参考にし、掲載した5つの確認操作と画面はRHEL 10.2/systemd 257の実測結果に基づいています。

コメント