Introduction
Une planification fiable nécessite davantage de preuves qu'un récapitulatif de play réussi. Vous déploierez un programme de rapport protégé pour un utilisateur ordinaire, gérerez une entrée cron nommée stable, observerez les exécutions naturelles, mettrez à jour sa phase et supprimerez une entrée temporaire séparée. La vérification finale observera une nouvelle exécution du planificateur tout en préservant la tâche existante sans rapport.
Déployer un rapport d'utilisateur ordinaire et une planification nommée
Dans cette étape, vous déploierez un programme de rapport fourni et le planifierez pour l'utilisateur automation sur les deux hôtes gérés.
Cron est installé et son démon s'exécute déjà comme prérequis. Les nœuds n'exécutent pas systemd. Chaque crontab automation contient aussi une entrée keep-existing-report sans rapport ; préservez-la. Le module cron gère une entrée nommée stable au lieu de remplacer toute la crontab de l'utilisateur.
Entrez dans le projet et examinez le programme fourni du contrôleur :
cd /home/labex/project
cat files/host-report.sh
Le programme ajoute un horodatage UTC en secondes depuis l'époque, le véritable nom d'hôte et l'argument de phase à un journal géré protégé. Umask 027 donne aux nouveaux journaux le mode 0640. Laissez le programme inchangé et laissez cron l'exécuter naturellement ; l'invoquer manuellement ne démontrerait pas la planification.
Définissez la phase comme entrée réutilisable :
cat > group_vars/all.yml <<'YAML'
report_phase: initial
YAML
Créez le playbook. Une tâche cron possède les champs minute, heure, jour du mois, mois et jour de la semaine ; une étoile dans chaque champ déclenche une exécution par minute. Le name crée un marqueur Ansible utilisé pour les mises à jour ultérieures, et user automation sélectionne la crontab de cet utilisateur. Become permet de gérer la planification de cet utilisateur nommé et les propriétaires de fichiers explicites ; il ne fait pas exécuter le programme planifié sous 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
Validez et appliquez :
ansible-playbook reporting.yml --syntax-check
ansible-playbook reporting.yml
Examinez les véritables crontabs automation. La commande s'exécute avec become pour pouvoir nommer explicitement le compte interrogé :
ansible all -b -m ansible.builtin.command -a 'crontab -u automation -l'
Chacune doit contenir un marqueur ansible-host-report et la commande à chaque minute, ainsi que l'entrée keep-existing-report inchangée. Une ligne de crontab seule ne prouve pas l'exécution.
Attendez le premier déclenchement naturel du planificateur. timeout borne l'attente à 90 secondes ; la boucle until de bash vérifie toutes les deux secondes l'existence d'un journal non vide. La commande lit uniquement l'état pendant que cron crée le journal :
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'
Chacun doit avoir un enregistrement tel que time= host=web1 phase=initial, avec le véritable nom d'hôte correspondant sur web2. Les horodatages varient et doivent correspondre à la planification naturelle par minute. Si l'attente bornée échoue, examinez la planification et le démon en cours au lieu d'écrire vous-même un journal de réussite.
Mettre à jour une entrée nommée et observer la nouvelle phase
Dans cette étape, vous changerez l'entrée de la tâche tout en préservant son identité stable et la planification sans rapport.
Mettez à jour la valeur de phase enregistrée. La tâche cron produira la nouvelle commande tout en gardant le même nom :
cat > group_vars/all.yml <<'YAML'
report_phase: verified
YAML
ansible-playbook reporting.yml
Examinez de nouveau les deux crontabs :
ansible all -b -m ansible.builtin.command -a 'crontab -u automation -l'
Il doit toujours y avoir exactement une entrée ansible-host-report par hôte, se terminant maintenant par verified. Réutiliser son nom met à jour l'entrée existante au lieu d'accumuler une deuxième planification. Keep-existing-report doit rester inchangé.
Attendez une nouvelle exécution naturelle utilisant la phase mise à jour. grep -q vérifie la présence d'un enregistrement correspondant sans l'afficher ; timeout et la boucle until bornent cette attente :
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'
Les deux doivent maintenant contenir un nouvel enregistrement phase=verified issu du véritable planificateur. Les anciens enregistrements initial constituent un historique utile et doivent rester. Modifier une commande crontab ne change pas rétroactivement les anciennes lignes du journal.
Supprimer uniquement une tâche temporaire nommée et garder les rapports stables
Dans cette étape, vous supprimerez une planification temporaire par son nom stable et vérifierez que le rapport prévu de l'utilisateur ordinaire continue à s'exécuter.
Créez une entrée temporaire nommée inoffensive avec une tâche cron ad hoc. Elle planifie /usr/bin/true à minuit et fournit une véritable entrée à supprimer :
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'
Écrivez un petit playbook de nettoyage. State absent et les name/user correspondants suppriment uniquement cette entrée gérée. Ne videz ni ne remplacez la crontab complète :
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'
Le marqueur temporaire et sa commande doivent avoir disparu. ansible-host-report avec la phase verified et keep-existing-report doivent tous deux rester.
Répétez les deux déclarations :
ansible-playbook reporting.yml
ansible-playbook cleanup.yml
Les deux playbooks doivent indiquer changed=0, unreachable=0 et failed=0 pour les deux hôtes. Cron peut continuer à ajouter indépendamment des enregistrements au journal ; ces enregistrements naturels d'exécution ne rendent pas le déploiement déclaratif non idempotent.
La vérification finale examine les tâches nommées des utilisateurs ordinaires, le programme déployé exact et les journaux protégés, puis attend un autre déclenchement naturel du planificateur sur les deux hôtes. Cela peut prendre environ une minute. Laissez la planification des rapports et le démon en cours pour que cette observation établisse l'exécution continue plutôt qu'un fichier de réussite préparé manuellement.
Résumé
Vous avez géré des entrées cron nommées stables pour l'utilisateur ordinaire prévu, observé l'exécution planifiée réelle, mis à jour l'entrée de commande sans dupliquer la tâche et supprimé uniquement une entrée temporaire. Les permissions explicites du programme et du journal, ainsi que la préservation des planifications sans rapport, ont gardé la portée claire. Le déploiement s'est répété sans changement tandis que le rapport continuait à s'exécuter naturellement.



