📚 連載:Ansibleが理解できない理由はLinuxにあった【OS編】第5回:【サービスが起動しない理由】systemdの仕組みを理解する
Linuxの仕組みからAnsibleを理解するシリーズです。
0️⃣ Ansibleの仕組み
1️⃣ Linuxの構造(Kernel / Shell / Filesystem)
2️⃣ command not foundの原因:PATH
3️⃣ SSH接続できない理由:鍵認証とポート
4️⃣ Permission deniedの原因:ユーザーと権限
5️⃣ サービスが起動しない理由:systemd
6️⃣ cronが動かない理由:PATH問題
7️⃣ ディスク満杯になる理由
8️⃣ サーバーが遅くなる理由
🗺️ 初めての方・シリーズの全体像を知りたい方はこちら
本記事は、OSの仕組みからAnsible設計までを繋ぐ連載シリーズの一部です。
「どこから読み始めればいいか」あるいは、「OS/Shell/Ansible編の関係性」 について把握されたい場合は、以下の統合ガイドで整理しています。
📑 【OS編】全体のまとめはこちら
→ Ansibleが理解できない理由はLinuxにあった【OS編】まとめ
📑 連載の移動
前の記事:【OS編】第4回 | 次の記事:【OS編】第6回
シリーズ全体構造(学習 × 問題解決)
本シリーズは
「理解(各記事)」と「問題解決(逆引き辞典)」を組み合わせて
スキルを身につける構成になっています。
この図は、どこから学び、どこに進めばよいかを示した“ロードマップ”です。
📍 現在の位置
現在はこの図の「OS編 第5回」になります
📍 はじめに:この記事のスタンス
ファイル権限(Permission)の問題を解消し、サービスを起動させる段階で直面する以下の事象を整理します。
-
「FAILED! => msg: Job for nginx.service failed... と出力され、起動タスクが失敗する」
-
「手動での systemctl start は成功するが、Ansible経由の実行時のみ失敗する」
-
「state: started を定義しているが、Ansibleが失敗と判定した技術的根拠を説明できない」
⚠️ 注意事項
本稿は、Linuxのプロセス管理や systemd の全機能を網羅することを目的とした資料ではありません。
主眼に置くのは、Ansibleにおいて service / systemd モジュール が失敗した際、
「OS側のどのステータスに起因し、どのログを参照して解決すべきか」を特定する手順の確立です。
「Playbookの定義は正しいにもかかわらず、サービスが起動しない」
この実務上の課題を解消するため、Linuxの「systemd」による状態管理の仕組みと、Ansibleにおける実行成否の判定ロジックの相関関係を解説します。
📋 目次
- 前回の振り返り(第4回)
- 逆引き辞典との連動
- systemdとは何か:サービス状態の「管理リスト」
- なぜサービスが起動しないのか:OSによる3つの「制限」パターン
- systemctl status の読み方:OSが残した「事実」を確認する
- 実機検証:Ansibleによるサービス操作と状態の変化
- 実務で遭遇する「サービスが起動・継続しない」3つの要因
- まとめ:事象の特定を迅速化する「調査のプロセス」
- 次回予告
- 連載一覧:Ansibleが理解できない理由はLinuxにあった
1. 前回の振り返り(第4回)
前回の記事では、ファイル操作の根幹である Permission denied の構造を解説しました。
「所有者・グループ・その他」の属性リストと自分を照合し、不一致があれば become: yes による特権昇格で解決を図るという流れを整理しました。
今回は、その一歩先のステップです。適切な権限でファイルを配置した後、「プログラムをサービスとして正常に稼働させる」 プロセスにおいて発生する問題を整理します。
2. 逆引き辞典との連動
具体的なエラー名から原因を特定したい場合は、以下の逆引き辞典を活用してください。
Ansibleが理解できない理由はLinuxにあった :【保存版】Ansibleトラブル逆引き辞典|エラー別の原因と解決フローまとめ
- まず「逆引き辞典」で該当ステップを特定する
- 次に「本編(各連載記事)」で仕組みを理解する
3. systemdとは何か:サービス状態の「管理リスト」
Linuxにおいてプログラムをバックグラウンドで常駐実行させる際、その「起動・停止・現在の状態」を一括して制御しているのが systemd です。
実務上、私たちが systemctl コマンドで行っている操作は、systemdが内部で保持している 「サービス状態の管理リスト」 の更新要求に他なりません。
🔍 systemdを構成する「3つの要素」
systemdは、以下の要素が連携することでサービスのライフサイクルを管理しています。
| 構成要素 | 役割 | 実務での位置付け |
|---|---|---|
| systemd | 管理主体 | 各プロセスの実行状態を監視・制御する基盤システム。 |
| systemctl | 操作インターフェース | 管理リストの参照や更新を行うための制御コマンド。 |
| Unitファイル | 起動の定義書 |
/lib/systemd/system/*.service 等に配置される設定ファイル。 |
-
Ansibleのタスク成否は、この
systemdの管理リストが「期待した状態(Active等)」に更新されたかどうかで判定されます。 -
Ansible側の実行ステータスは、
systemctlの戻り値(=OS側の判定結果)に完全に依存しています。
この「リストの更新」と「Ansibleの成否判定」が技術的にどのように紐付いているのかについては、後述する「5. Ansibleのsystemdモジュール」にて詳述します。
4. なぜサービスが起動しないのか:OSによる3つの「制限」パターン
systemctl start を実行してエラーが返される理由は、第4回で解説した「権限」の仕組みと同様に、OS側のチェックを通過できていないことにあります。
Ansibleで Job for nginx.service failed と出力された際、プロセスが起動を制限される理由は、主に以下の3つのチェック項目のいずれかに該当しています。
🔍 systemdによる起動時の判定ステップ
systemdは、サービス起動時に以下の項目を順次確認し、条件を満たさない場合は起動を許可しません。
| 判定ステップ | 拒絶される主な理由(実務例) |
|---|---|
| Step 1: 設定ファイルの整合性 |
nginx.conf 等に構文エラーがあり、プログラムが動作を開始できない。 |
| Step 2: 実行リソースの確保 | 指定したポート(例: 80番)を既に別のプロセスが占有している。 |
| Step 3: 実行権限の有効性 | プロセスが、ログファイルやディレクトリに対して必要なアクセス権限(w)を持っていない。 |
Ansibleから起動指示を出しても、OS側のこれらの判定項目に不備があれば、systemdは起動を許可しません。
5. systemctl status の読み方:OSが残した「事実」を確認する
Ansibleによる操作が失敗した際、その理由を特定するには、systemdが管理している 「状態リストの詳細」 を参照するのが最短ルートです。
systemctl status nginx
🔍 判定のメカニズム(ログから事実を拾う)
第4回で解説した「属性リスト」の概念と同様に、コマンドの実行結果を以下の 「3つの事実」 に分解して確認します。
| 確認対象 | (ログの項目) | 判定内容 |
|---|---|---|
| Step 1 | Active: |
failed や inactive であれば、プロセスが常駐できていない事実。 |
| Step 2 | Main PID: |
code=exited, status=1/FAILURE 等、OSがプロセスの異常終了を検知した事実。 |
| Step 3 | Log(末尾) | OSがサービスの起動・継続を制限した直接の理由。 |
-
結論:Ansibleのエラーは「OS側の制限」の反映
Ansibleが実行結果としてFAILEDを出力したとき、その根本原因はAnsible自体の不具合ではなく、多くの場合この Step 3 に記録された「OS側の制限」 にあります。
6. 実機検証:Ansibleによるサービス操作と状態の変化
これまでに解説した「systemdの管理リスト」が、実際のAnsible実行時にどのように反映されるかを検証します。
6-1. 検証前の状況確認(事前の事実確認)
本検証では、リモートノードに直接ログインするのではなく、コントローラーノードからAnsibleのad-hocコマンドを使用して、対象の状態を一括で取得します。
# パッケージの導入状態を確認
(ansible) [ansible@localhost ansible-test]$ ansible test_servers -i ../inventory.ini -a "rpm -q nginx"
192.168.1.21 | CHANGED | rc=0 >>
nginx-1.20.1-24.el9_7.2.rocky.0.1.x86_64
# サービスの状態を確認
(ansible) [ansible@localhost ansible-test]$ ansible test_servers -i ../inventory.ini -a "systemctl is-active nginx"
192.168.1.21 | FAILED | rc=3 >>
inactive
-
分析:
rpm -qの結果によりパッケージの導入が確認できました。一方で、is-activeの結果はinactive(戻り値 3)であり、現時点でプロセスは稼働していないという「客観的な事実」が手元の端末から確認できました。
6-2. 検証内容:コントローラーノードからのサービス起動
【検証①】失敗例:特権昇格(become)の記述漏れ
実務で頻発する、become: yes を指定し忘れたケースを再現します。Ansibleの構文(Playbookの書き方)自体に間違いはありませんが、実行時にどのような結果になるかを確認します。
使用するPlaybook(deploy_nginx_error.yml):
- name: Nginxサービスを起動(記述漏れあり)
hosts: test_servers
# ここで become: yes をあえて記述しない
tasks:
- name: サービスを起動状態にする
ansible.builtin.systemd:
name: nginx
state: started
実行コマンド
ansible-playbook -i ../inventory.ini deploy_nginx_error.yml
実行結果(ログ):
PLAY [Nginxサービスを起動(記述漏れあり)] **************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************************
ok: [192.168.1.21]
TASK [サービスを起動状態にする] *************************************************************************************************************************************************************
fatal: [192.168.1.21]: FAILED! => {"changed": false, "msg": "Unable to start service nginx: Failed to start nginx.service: Access denied\nSee system logs and 'systemctl status nginx.service' for details.\n"}
PLAY RECAP **********************************************************************************************************************************************************************************
192.168.1.21 : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
(ansible) [ansible@localhost ansible-test]$
-
分析:
Access denied(アクセス拒否)が発生しました。
Ansibleは指示通りにsystemctl start nginxを発行しようとしましたが、リモートノード側で実行しているユーザーに権限がないため、OS側がその操作を制限した事実が分かります。
Ansibleのメッセージ内に「詳細は systemctl status を見よ」とある通り、Ansibleはあくまで「OS側の判定結果」を中継しているに過ぎません。
【検証②】成功例:正しい権限での実行(become: yes)
次に、become: yes(特権昇格)を明記し、管理者権限で実行します。
使用するPlaybook(deploy_nginx_success.yml):
- name: Nginxサービスを起動(正常)
hosts: test_servers
become: yes # 正しく特権昇格を指定
tasks:
- name: サービスを起動状態にする
ansible.builtin.systemd:
name: nginx
state: started
enabled: yes
実行コマンド
ansible-playbook -i ../inventory.ini deploy_nginx_success.yml
実行結果(ログ):
(ansible) [ansible@localhost ansible-test]$ ansible-playbook -i ../inventory.ini deploy_nginx_success.yml
PLAY [Nginxサービスを起動(正常)] ****************************************************
TASK [Gathering Facts] ************************************************************
ok: [192.168.1.21]
TASK [サービスを起動状態にする] ****************************************************
changed: [192.168.1.21]
PLAY RECAP ************************************************************************
192.168.1.21 : ok=2 changed=1 unreachable=0 failed=0 ...
-
分析:
changedとなり、指示が正常に受理されました。
6-3. 検証後の状況確認(事後の事実確認)
最後に、リモートノードの「現在の事実」を再び ad-hoc コマンドで確認します。
- 実行結果:
(ansible) [ansible@localhost ansible-test]$ ansible test_servers -i ../inventory.ini -a "systemctl is-active nginx"
192.168.1.21 | CHANGED | rc=0 >>
active
-
分析: ステータスが
active(戻り値 0)に変化しました。
Ansible によって OS 側の「管理リスト」が書き換わり、サービスが正常に稼働したことが、コントローラーノード側の操作だけで物理的に確認できました。
7. 実務で遭遇する「サービスが起動・継続しない」3つの要因
これまでの検証結果を踏まえ、実務においてAnsibleによるサービス管理が期待通りに動作しない主な要因を整理します。
7-1. 特権昇格(become: yes)の欠落
第6セクションの検証①で確認した通り、systemdの管理リストを操作するには管理者権限が必須です。
-
事象:
Access deniedまたはPermission deniedエラーによりタスクが失敗する。 -
技術的背景: Ansibleが実行する
systemctlコマンドに対し、OS側が権限不足を理由に操作を制限するためです。 -
対策: サービス操作を含むタスク、あるいはPlaybook全体に対して
become: yesを明記し、適切な特権で実行します。
7-2. 実行状態(started)と自動起動(enabled)の混同
Ansibleの systemd モジュールにおいて、現在の状態とOS再起動後の挙動を区別して定義する必要があります。
-
事象: Playbook実行直後はサービスが稼働しているが、OSを再起動するとサービスが停止している。
-
技術的背景:
state: startedは「今、プロセスを起動すること」のみを指示し、enabled: yesは「OS起動時にサービスを有効化する」というsystemdの予約リスト(シンボリックリンクの作成)を更新する操作であるためです。 -
対策: 恒久的なサービス稼働が必要な場合は、両方のパラメータを明示的に指定します。
7-3. 設定変更後の再起動(restarted)プロセスの欠如
設定ファイル(nginx.conf 等)をAnsibleで更新しても、稼働中のプロセスには即座に反映されません。
-
事象: Playbookで設定ファイルを更新しタスクも成功(changed)しているが、実際の挙動が古い設定のままである。
-
技術的背景: プロセスは起動時に読み込んだメモリ上の設定で動作を続けるため、OS側の管理リストに対してプロセスの再生成(restart)を明示的に指示する必要があります。
-
対策: 設定ファイルの配布タスクに
handlersを紐付けるか、state: restartedを実行してプロセスの更新を確定させます。
8. まとめ:事象の特定を迅速化する「調査のプロセス」
Ansibleによるサービス操作で FAILED が出力された際は、以下の3ステップに従って「OS側の事実」を確認してください。
【サービス起動失敗時の調査手順】
1. 実行権限の確認
→ タスクに become: yes が適切に定義されているか
2. systemd 管理リストのステータス確認
→ 対象ホストで systemctl status を実行し、Active状態と戻り値を確認
3. 実行ログに記録された制限理由の特定
→ ポートの競合、設定ファイルの不備、ディレクトリへのアクセス権限を確認
-
本質的な視点
サービスの起動失敗は、Ansibleの構文エラーではなく、その大半が 「OS側でのプロセス稼働条件の未充足」 です。
第3回で解説した「接続」、第4回で解説した「権限」と同様に、「OS側の管理リスト(status)にどのような事実が記録されているか」。この一点を正確に把握することが、トラブルシューティングにおける最短の経路となります。
9. 次回予告
サービス管理のプロセスを完了した後に直面するのが、以下の事象です。
「手動でのスクリプト実行は成功するが、cronによる定期実行のみ失敗する」
Ansibleの cron モジュールを使用して設定自体は正常に完了しているにもかかわらず、なぜ処理が意図通りに動作しないのか。
その要因は、第2回で解説した 「PATH(環境変数)」 の概念と、cron固有の 「限定的な実行環境」 にあります。
次回、第6回:【cronが動かない理由】手動では動くのに失敗する原因 をお送りします。
📑 連載の移動
前の記事:【OS編】第4回 | 次の記事:【OS編】第6回
📑 【OS編】全体のまとめはこちら
→ Ansibleが理解できない理由はLinuxにあった【OS編】まとめ
🗺️ 初めての方・シリーズの全体像を知りたい方はこちら
本記事は、OSの仕組みからAnsible設計までを繋ぐ連載シリーズの一部です。
「どこから読み始めればいいか」あるいは、「OS/Shell/Ansible編の関係性」 について把握されたい場合は、以下の統合ガイドで整理しています。
10. 連載一覧:Ansibleが理解できない理由はLinuxにあった
| 回数とタイトル | 内容(概要) |
|---|---|
| Ansibleが理解できない理由はLinuxにあった【OS編】:【保存版】Ansibleトラブル逆引き辞典(Linux / SSH / Shellエラー対応 | Ansibleで発生するエラー(UNREACHABLE / Permission denied / command not found など)を「エラーから逆引き」で調べられる実務向け記事。各回の内容と対応しており、トラブル時の入口として使える。 |
| 第0回:【なぜAnsibleは理解できないのか】仕組みを分解してみる | Ansibleは「Linux操作の自動化」ツール。Ansible → SSH → Shell → Linux の構造を理解し、シリーズ全体の土台を作る。 |
| 第1回:【なぜLinuxが分からないと詰むのか】Kernel / Shell / Filesystemの全体像 | Linuxの基本構造を理解することで、Ansibleが内部で何をしているのか(Shell実行・プロセス・ファイル操作)を把握できるようになる。 |
| 第2回:【Ansibleでハマる】command not foundの原因はPATHだった(環境変数の正体) | Ansible実行時に発生する「command not found」の原因はPATHにある。環境変数の仕組みを理解しないとエラーを解決できない。 |
| 第3回:AnsibleのSSH接続が失敗すると UNREACHABLE エラーになる。(Connection refused / Permission denied / Timeout など) | AnsibleのSSH接続が失敗すると UNREACHABLE エラーになる。SSH(鍵認証・ポート・Firewall)を理解することで原因を特定できる。 |
| 第4回:【Permission deniedの正体】Linuxユーザーと権限の仕組み | Ansibleのbecome(sudo)で発生する Permission denied の原因はLinux権限にある。ユーザー・グループ・権限の仕組みを理解する。 |
| 第5回:【サービスが起動しない理由】systemdの仕組みを理解する | Ansibleのservice / systemdタスクが失敗する原因はLinux側にある。systemdの仕組みを理解することで原因を特定できる。 |
| 第6回:【cronが動かない理由】手動では動くのに失敗する原因 | Ansibleで設定したcronが動かない原因は環境差分(PATHなど)にある。cron特有の実行環境を理解することで解決できる。 |
| 第7回:【No space left on device】ディスク容量不足の原因と調査方法(df / du / log) | Ansible実行時のディスク不足エラーはLinuxのログ肥大化や容量管理が原因。df / duを使った調査方法を解説する。 |
| 第8回:【サーバーが遅い】原因の見つけ方(CPU / メモリ / プロセス) | Ansible実行が遅い・失敗する原因はサーバー負荷の可能性がある。CPU・メモリ・プロセスの見方を理解して原因を特定する。 |