Introducción
Una programación fiable necesita más pruebas que un resumen correcto del play. Desplegarás un programa protegido de informes para un usuario normal, administrarás una entrada cron con nombre estable, observarás ejecuciones naturales, actualizarás su fase y eliminarás una entrada temporal separada. La comprobación final observará una nueva ejecución del planificador mientras conserva la tarea existente ajena.
Desplegar un informe de usuario normal y una programación con nombre
En este paso, desplegarás un programa de informes proporcionado y lo programarás para el usuario automation en ambos hosts administrados.
Cron está instalado y su demonio ya está en ejecución como requisito previo. Los nodos no ejecutan systemd. Cada crontab de automation también contiene una entrada ajena keep-existing-report; consérvala. El módulo cron administra una entrada con nombre estable en lugar de sustituir todo el crontab del usuario.
Entra en el proyecto e inspecciona el programa proporcionado del controlador:
cd /home/labex/project
cat files/host-report.sh
El programa añade una marca de tiempo de época UTC, el nombre real de host y el argumento de fase a un registro administrado protegido. Umask 027 da a los nuevos archivos de registro permisos 0640. Deja el programa sin cambios y permite que cron lo ejecute de forma natural; invocarlo manualmente no demostraría la programación.
Define la fase como entrada reutilizable:
cat > group_vars/all.yml <<'YAML'
report_phase: initial
YAML
Crea el playbook. Una tarea cron tiene campos de minuto, hora, día del mes, mes y día de la semana; un asterisco en cada campo la ejecuta una vez por minuto. El nombre crea un marcador de Ansible usado para actualizaciones posteriores, y user automation selecciona el crontab de ese usuario. Become permite administrar la programación de este usuario nombrado y la propiedad explícita de archivos; no hace que el programa programado se ejecute como 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
Valida y aplica:
ansible-playbook reporting.yml --syntax-check
ansible-playbook reporting.yml
Inspecciona los crontabs reales de automation. El comando se ejecuta con become para poder nombrar explícitamente la cuenta consultada:
ansible all -b -m ansible.builtin.command -a 'crontab -u automation -l'
Cada uno debería contener un marcador ansible-host-report y el comando de cada minuto, además de la entrada keep-existing-report sin cambios. Una línea de crontab por sí sola no demuestra ejecución.
Espera el primer ciclo natural del planificador. timeout limita la espera a 90 segundos; el bucle until de bash comprueba cada dos segundos si hay un registro no vacío. El comando solo lee el estado mientras cron crea el registro:
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'
Cada uno debería tener un registro como time= host=web1 phase=initial, con el nombre de host real correspondiente en web2. Las marcas de tiempo varían y deberían alinearse con la programación natural por minuto. Si la espera acotada falla, inspecciona la programación y el demonio en ejecución en lugar de escribir tú mismo un registro de éxito.
Actualizar una entrada con nombre y observar la nueva fase
En este paso, cambiarás la entrada de la tarea conservando su identidad estable y la programación ajena.
Actualiza el valor guardado de fase. La tarea cron generará el nuevo comando conservando el mismo nombre:
cat > group_vars/all.yml <<'YAML'
report_phase: verified
YAML
ansible-playbook reporting.yml
Inspecciona ambos crontabs otra vez:
ansible all -b -m ansible.builtin.command -a 'crontab -u automation -l'
Debería seguir habiendo exactamente una entrada ansible-host-report por host, que ahora termina en verified. Reutilizar su nombre actualiza la entrada existente en lugar de acumular una segunda programación. Keep-existing-report debe permanecer sin cambios.
Espera una nueva ejecución natural usando la fase actualizada. grep -q comprueba si hay un registro coincidente sin imprimirlo; timeout y el bucle until mantienen acotada esta espera:
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'
Ambos deberían contener ahora un nuevo registro phase=verified procedente del planificador real. Los registros initial anteriores son un historial útil y deberían conservarse. Actualizar un comando del crontab no cambia retroactivamente las líneas antiguas del registro.
Eliminar solo una tarea temporal con nombre y mantener estables los informes
En este paso, eliminarás una programación temporal por su nombre estable y verificarás que el informe previsto del usuario normal sigue ejecutándose.
Crea una entrada temporal inofensiva con nombre usando una tarea cron ad hoc. Programa /usr/bin/true a medianoche y proporciona una entrada real que eliminar:
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'
Escribe un pequeño playbook de limpieza. State absent y el name/user coincidente eliminan únicamente esa entrada administrada. No vacíes ni sustituyas el crontab completo:
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'
El marcador y el comando temporales deberían haber desaparecido. Tanto ansible-host-report con fase verified como keep-existing-report deberían permanecer.
Repite ambas declaraciones:
ansible-playbook reporting.yml
ansible-playbook cleanup.yml
Ambos playbooks deberían informar changed=0, unreachable=0 y failed=0 para ambos hosts. Cron puede seguir añadiendo registros de forma independiente; esos registros naturales de ejecución no hacen que el despliegue declarativo deje de ser idempotente.
La comprobación final inspecciona las tareas con nombre del usuario normal, el programa exacto desplegado y los registros protegidos, y después espera otro ciclo natural del planificador en ambos hosts. Puede tardar alrededor de un minuto. Deja en ejecución la programación del informe y el demonio para que esta observación pueda demostrar la ejecución continua en lugar de un archivo de éxito preparado manualmente.
Resumen
Has administrado entradas cron con nombre estable para el usuario normal previsto, observado la ejecución programada real, actualizado la entrada del comando sin duplicar la tarea y eliminado únicamente una entrada temporal. Los permisos explícitos del programa y del registro y la conservación de programaciones ajenas mantuvieron claro el alcance. El despliegue se repitió sin cambios mientras el informe siguió ejecutándose de forma natural.



