はじめに
信頼できるスケジューリングには、Play の成功 recap 以上の証拠が必要です。一般ユーザー用の保護されたレポートプログラムを配置し、安定した名前付き cron エントリを管理して、自然なスケジュール実行を観察し、フェーズを更新して、別の一時エントリを削除します。最終チェックは、無関係の既存ジョブを維持しながら、新たなスケジューラー実行を観察します。
一般ユーザーのレポートと名前付きスケジュールを配置する
このステップでは、提供されたレポートプログラムを配置し、両管理対象ホストの automation ユーザーにスケジュールします。
前提として cron はインストール済みで、デーモンも稼働中です。ノードでは systemd は動作していません。各 automation の crontab には、無関係の keep-existing-report エントリもあります。それを維持してください。cron モジュールは、ユーザーの crontab 全体を置き換えず、安定した名前付きエントリを管理します。
プロジェクトに移動し、提供されたコントローラーのプログラムを調べます。
cd /home/labex/project
cat files/host-report.sh
このプログラムは、UTC エポックタイムスタンプ、実際のホスト名、フェーズ引数を、保護された管理対象ログに追記します。Umask 027 により、新しいログファイルのモードは 0640 になります。プログラムは変更せず、cron に自然に実行させてください。手動で呼び出しても、スケジュールの実証にはなりません。
フェーズを再利用可能な入力として定義します。
cat > group_vars/all.yml <<'YAML'
report_phase: initial
YAML
Playbook を作成します。cron ジョブには minute、hour、日、month、weekday のフィールドがあり、各フィールドのアスタリスクは毎分 1 回の実行を意味します。name は、後の更新に使う Ansible マーカーを作成し、user automation はそのユーザーの crontab を選択します。Become は、その指定ユーザーのスケジュールと明示的なファイル所有権を管理できるようにするもので、定期実行プログラムを root として実行するものではありません。
cat > reporting.yml <<'YAML'
- name: Manage a scheduled ordinary-user host report
hosts: all
gather_facts: false
become: true
tasks:
- name: Prepare the ordinary user's reporting directory
ansible.builtin.file:
path: /home/automation/reporting
state: directory
owner: automation
group: automation
mode: "0750"
- name: Deploy the supplied report program
ansible.builtin.copy:
src: /home/labex/project/files/host-report.sh
dest: /home/automation/reporting/host-report.sh
owner: automation
group: automation
mode: "0750"
- name: Keep the named report schedule present
ansible.builtin.cron:
name: ansible-host-report
user: automation
minute: "*"
hour: "*"
day: "*"
month: "*"
weekday: "*"
job: "/home/automation/reporting/host-report.sh {{ report_phase }}"
YAML
検証し、適用します。
ansible-playbook reporting.yml --syntax-check
ansible-playbook reporting.yml
実際の automation の crontab を調べます。照会するアカウントを明示できるよう、コマンドは become 付きで実行します。
ansible all -b -m ansible.builtin.command -a 'crontab -u automation -l'
それぞれに 1 つの ansible-host-report マーカーと毎分実行のコマンド、そして変更されていない keep-existing-report エントリが含まれるはずです。crontab の行だけでは実行の証明にはなりません。
最初の自然なスケジューラー実行タイミングを待ちます。timeout は待機を 90 秒に制限し、bash の until ループは 2 秒ごとに空でないログを確認します。cron がログを作成する間、このコマンドは状態を読むだけです。
ansible all -m ansible.builtin.command -a "timeout 90 bash -c 'until test -s /home/automation/reporting/host-report.log; do sleep 2; done'"
ansible all -m ansible.builtin.command -a 'cat /home/automation/reporting/host-report.log'
それぞれに time= host=web1 phase=initial のような記録があり、web2 には対応する実際のホスト名があるはずです。タイムスタンプは変動し、自然な毎分のスケジューリングと一致するはずです。制限時間内の待機に失敗した場合は、自分で成功ログを書くのではなく、スケジュールと稼働デーモンを調べてください。
1 つの名前付きエントリを更新して新しいフェーズを観察する
このステップでは、安定した識別名と無関係のスケジュールを維持しながら、ジョブの入力を変えます。
保存されたフェーズ値を更新します。cron タスクは、同じ名前を維持しながら新しいコマンドを生成します。
cat > group_vars/all.yml <<'YAML'
report_phase: verified
YAML
ansible-playbook reporting.yml
両方の crontab をもう一度調べます。
ansible all -b -m ansible.builtin.command -a 'crontab -u automation -l'
各ホストには引き続き、正確に 1 つの ansible-host-report エントリがあり、今度は verified で終わるはずです。名前を再利用すると、2 つ目のスケジュールを蓄積せず、既存のエントリが更新されます。keep-existing-report は変更しないでください。
更新されたフェーズを使う、新しい自然な実行を待ちます。grep -q は、一致するログ記録を表示せずに確認し、timeout と until ループは待機を制限します。
ansible all -m ansible.builtin.command -a "timeout 90 bash -c 'until grep -q phase=verified /home/automation/reporting/host-report.log; do sleep 2; done'"
ansible all -m ansible.builtin.command -a 'cat /home/automation/reporting/host-report.log'
今度は両方に、実際のスケジューラーによる新しい phase=verified 記録が含まれるはずです。以前の initial 記録は有用な履歴なので、そのまま残してください。crontab コマンドを更新しても、古いログ行が遡って変わるわけではありません。
名前付きの一時ジョブだけを削除し、レポートを安定させる
このステップでは、安定した名前で一時スケジュールを削除し、意図した一般ユーザーのレポートが引き続き実行されることを検証します。
アドホックの cron タスクで、害のない名前付き一時エントリを作成します。真夜中に /usr/bin/true をスケジュールし、削除するための実際のエントリを用意します。
ansible all -b -m ansible.builtin.cron -a 'name=ansible-temporary-report user=automation minute=0 hour=0 job=/usr/bin/true'
ansible all -b -m ansible.builtin.command -a 'crontab -u automation -l'
小さなクリーンアップ用 Playbook を記述します。state absent と、一致する name/user は、その管理対象エントリだけを削除します。crontab 全体を空にしたり、置き換えたりしないでください。
cat > cleanup.yml <<'YAML'
- name: Remove only the obsolete named schedule
hosts: all
gather_facts: false
become: true
tasks:
- name: Remove the obsolete report entry by its stable name
ansible.builtin.cron:
name: ansible-temporary-report
user: automation
state: absent
YAML
ansible-playbook cleanup.yml
ansible all -b -m ansible.builtin.command -a 'crontab -u automation -l'
一時マーカーとコマンドはなくなるはずです。フェーズ verified の ansible-host-report と keep-existing-report の両方が残る必要があります。
両方の宣言を繰り返します。
ansible-playbook reporting.yml
ansible-playbook cleanup.yml
両 Playbook が両ホストで changed=0、unreachable=0、failed=0 を報告するはずです。Cron は独立してログ記録を追記し続ける場合がありますが、こうした自然な実行時の記録によって、宣言的な配置が非冪等になるわけではありません。
最終チェックは、名前付きの一般ユーザージョブ、正確に配置されたプログラム、保護されたログを調べ、その後、両ホストでさらにもう 1 回の自然なスケジューラー実行タイミングを待ちます。約 1 分かかる場合があります。手動で準備した成功ファイルではなく、継続的な実行を観察できるよう、レポートのスケジュールとデーモンを動かしたままにしてください。
まとめ
意図した一般ユーザーの安定した名前付き cron エントリを管理し、実際の定期実行を観察して、ジョブを複製せずにコマンド入力を更新し、一時エントリだけを削除しました。明示的なプログラム・ログの権限と、無関係のスケジュールの維持により、範囲を明確に保ちました。レポートが自然に実行され続ける間も、配置の繰り返しには変更がありませんでした。



