Gérer des rapports d'hôte planifiés avec cron

LinuxBeginner
Pratiquer maintenant

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.