はじめに
既存の保守プログラムは、宣言的な自動化に慎重に統合する必要があります。command、shell、script を区別し、空白を含むパスを安全に渡して、読み取り専用の結果を分類し、実際のスクリプト出力に実行ガードを付けます。パイプラインと、コントローラーに委譲した受領記録によって、実行場所と失敗の伝播を観察できるようにします。また、実際の入力不足の失敗を発生させ、復旧します。
安全な引数でコマンドを直接実行する
このステップでは、command で管理対象の入力を調べ、空白を含むパスを保持し、読み取り専用の操作を正しく分類します。
状態管理には、copy や file などの宣言的なモジュールを優先してください。Command、shell、script は、既存の実行ファイルや保守プログラムの統合に役立ちます。command はシェルを使わずに管理対象の実行ファイルを実行するため、パイプやリダイレクトは解釈されません。argv 形式は、空白を含むパスも含め、各引数を個別に保持します。
準備済みの各対象には、承認済みデータ 1 行を含む /home/automation/maintenance input.txt と、前提条件の maintenance-ready があります。コントローラーには、後で使用する既存のスクリプトが scripts/ 以下にあります。これらの入力を維持してください。
コントローラーのプロジェクトに移動します。
cd /home/labex/project
argv を使う Playbook を作成します。空白を含むパスは、YAML リストの 1 項目です。register は、stdout と数値の終了コード rc を含む実行結果を取得します。ゼロは通常成功を意味し、コマンドの終了コードがゼロ以外の場合、通常はタスクが失敗します。
cat > maintenance.yml <<'YAML'
- name: Inspect maintenance inputs safely
hosts: all
gather_facts: false
tasks:
- name: Read the managed input with a space-safe argument list
ansible.builtin.command:
argv:
- /usr/bin/cat
- /home/automation/maintenance input.txt
register: input_result
changed_when: false
- name: Retain the inspected input in a managed record
ansible.builtin.copy:
dest: /home/automation/command-result.txt
content: "{{ input_result.stdout }}\n"
mode: "0640"
YAML
cat コマンドは読み取り専用なので、changed_when false はその結果を変更なしに分類します。この設定は、コマンドが実際に行うことではなく、報告を変えます。状態を変更するプログラムの変更を隠すために使ってはいけません。copy タスクは返された stdout を利用し、末尾の改行を明示した実際の管理対象記録を書きます。
Playbook をチェックして実行します。
ansible-playbook maintenance.yml --syntax-check
ansible-playbook maintenance.yml
両方の読み取りタスクは ok を報告し、最初の記録のコピーは各対象を変更するはずです。実際の記録を調べます。
ansible all -m ansible.builtin.command -a 'cat /home/automation/command-result.txt'
各記録は Approved maintenance data を含むはずです。この core バージョンでは、command はシェルを呼び出さなくても、Python を通じて環境変数の引数を展開できます。ドル記号で始まる引数をそのまま扱う必要がある場合は expand_argument_vars false を使ってください。この固定パスには不要です。
コントローラーのスクリプトを転送し、実際の出力をガードする
このステップでは、提供されたコントローラー側の保守スクリプトを両対象で呼び出し、不要な繰り返し実行を避けます。
実行前に、提供されたプログラムを調べてください。
cat scripts/host-maintenance.sh
このプログラムは、出力を作成する前に対象の maintenance-ready 入力を確認します。準備状態がなければ、エラーを表示して 42 で終了します。それ以外の場合、実際の対象ホスト名とラベル引数を含む、保護されたレポートを書きます。この小さなシェル実装は既存の統合入力です。通常のファイル設定には宣言的モジュールを使用してください。
script モジュールは、コントローラーのソースを対象に転送し、そこで実行します。これは、実行ファイルが管理対象ノードにすでに存在する必要がある command と異なります。下の引用符付きラベルは、空白を含む 1 つの引数のままです。creates パスは管理対象で確認され、そのレポートがすでに存在すれば、スクリプトはスキップされます。
script タスクを追記します。
cat >> maintenance.yml <<'YAML'
- name: Run the supplied controller script once per target report
ansible.builtin.script:
cmd: /home/labex/project/scripts/host-maintenance.sh 'Maintenance checked'
creates: /home/automation/maintenance-run/report.txt
register: maintenance_result
failed_when: maintenance_result.rc is defined and maintenance_result.rc != 0
YAML
登録結果の rc が failed_when を制御します。is defined のガードは、実行の終了コードを含まない結果に対応します。ignore_errors や failed_when false を使い、実際のスクリプト失敗を見かけの成功に変えないでください。
拡張した Playbook を実行します。
ansible-playbook maintenance.yml
両対象がレポートを作成するはずです。実際の出力を読みます。
ansible all -m ansible.builtin.command -a 'cat /home/automation/maintenance-run/report.txt'
各出力には自身のホスト名と label=Maintenance checked が含まれるはずです。同じ Playbook を繰り返します。
ansible-playbook maintenance.yml
対象のレポートが存在するためスクリプトはスキップされ、両 recap が changed=0 と、失敗・到達不能の対象なしを報告するはずです。Creates は存在のガードであり、内容の整合性を保つ仕組みではありません。既存の破損レポートを修復したり、スクリプト入力が変わったときに自動再生成したりはしません。
失敗を伝播させ、コントローラーの受領記録に委譲する
このステップでは、実際のパイプラインにだけ shell を使い、別々のコントローラーの受領記録を保存して、スクリプトの明らかな失敗を抑制せずに試します。
パイプは、あるコマンドの出力を別のコマンドの入力につなぐため、shell が必要です。Bash の pipefail は、パイプライン内のコマンド失敗を、最後の wc コマンドの成功で隠さずに失敗結果にします。以下のパイプラインは入力行数を数えるだけなので、対象の状態を変えずに読む changed_when false が適切です。failed_when は、予期しない行数も拒否します。
コントローラーに受領記録のディレクトリを作成します。委譲された各 copy は、元のインベントリ名を別々のファイル名に使用し、ホストが 1 つの共有記録を上書きするのを防ぎます。
mkdir -p receipts
パイプラインと受領記録のタスクを追記します。delegate_to localhost は、受領記録タスクだけをコントローラーで実行し、inventory_hostname は引き続き元の対象を識別します。become false は、コントローラーでのファイル作成を一般アカウント labex で行うようにします。
cat >> maintenance.yml <<'YAML'
- name: Count managed input lines with explicit pipeline failure propagation
ansible.builtin.shell: |
set -o pipefail
cat '/home/automation/maintenance input.txt' | wc -l
args:
executable: /bin/bash
register: line_result
changed_when: false
failed_when: line_result.rc != 0 or (line_result.stdout | trim) != '1'
- name: Store a per-target receipt on the controller
ansible.builtin.copy:
dest: "/home/labex/project/receipts/{{ inventory_hostname }}.txt"
content: |
host={{ inventory_hostname }}
input_lines={{ line_result.stdout | trim }}
mode: "0640"
delegate_to: localhost
become: false
YAML
保守の完全な手順を実行します。
ansible-playbook maintenance.yml
コントローラーの両受領記録を調べます。それぞれが自身の元のホストと input_lines=1 を示す必要があります。
cat receipts/web1.txt receipts/web2.txt
次に、web1 でスクリプトの実際の失敗分岐を試します。file モジュールで、ガード対象のレポートと準備入力を削除します。これらは練習ノード内の意図的な一時変更です。
ansible web1 -m ansible.builtin.file -a 'path=/home/automation/maintenance-run/report.txt state=absent'
ansible web1 -m ansible.builtin.file -a 'path=/home/automation/maintenance-ready state=absent'
次の実行では、web1 の script タスクが rc 42 と入力不足メッセージで失敗するはずです。|| は、想定した Playbook のゼロ以外の終了後もターミナルの作業を継続できるようにしますが、Ansible の失敗分類は変えません。
ansible-playbook maintenance.yml || printf 'Expected missing-readiness failure\n'
レポートのパスを調べます。スクリプト失敗後の web1 に、偽の成功レポートがあってはいけません。
ansible web1 -m ansible.builtin.stat -a 'path=/home/automation/maintenance-run/report.txt'
コントローラーの正確なソースから準備入力を復元し、完全な手順を再実行します。
printf 'Ready\n' > ready.txt
ansible web1 -m ansible.builtin.copy -a 'src=/home/labex/project/ready.txt dest=/home/automation/maintenance-ready mode=0644'
ansible-playbook maintenance.yml
web1 はレポートの再生成に成功するはずです。最後の繰り返しでは、変更、到達不能の対象、失敗がないはずです。
ansible-playbook maintenance.yml
読み取り専用の調査は引き続き実行され、ガード付きスクリプトは既存レポートをスキップし、各委譲された受領記録はコントローラー上に残ります。これにより、成功時の繰り返し実行を安定させながら、実際のエラー信号を維持できます。
まとめ
管理対象での直接実行には argv、コントローラーから対象へのプログラム転送には script、明示的な失敗伝播がある実際のパイプラインにだけ shell を使用しました。読み取り専用の変更報告、実際の creates ガード、抑制しない終了コードにより、結果を意味のあるものに保ちました。ホスト別に委譲した受領記録がコントローラー実行を実証し、入力不足の練習は、復旧した安定した手順で終了しました。


