
Quand une tâche échoue dans un playbook de 100 lignes, relancer tout est lent et frustrant. Ansible fournit un débogueur interactif qui ouvre un REPL Python au moment de l'échec : on inspecte les variables (p task_vars['x']), on modifie les arguments à chaud (task.args['name'] = 'nginx'), on rejoue la tâche modifiée (redo), on continue le playbook (continue). Activable au niveau task ou play avec debugger: on_failed.
Cette page détaille les 6 commandes du REPL, le workflow recommandé pour fixer une variable au runtime, et les 2 cas où ne pas activer le débogueur (CI/CD, AWX/AAP, cron).
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Activer
debugger: on_failedau niveau task ou play. - Inspecter variables, arguments, résultat avec
p. - Modifier les args (
task.args['x'] = 'y') et rejouer avecredo. - Injecter une variable manquante via
task_vars. - Quitter proprement (
continue,quit). - Quand NE PAS utiliser le débogueur (interactif requis).
Prérequis
Section intitulée « Prérequis »- Avoir lu Verbosité Ansible.
- Comprendre les variables et précédence.
Activer le débogueur
Section intitulée « Activer le débogueur »Trois niveaux d'activation, du plus fin au plus large.
Niveau task
Section intitulée « Niveau task »tasks: - name: Tâche fragile ansible.builtin.dnf: name: nginx state: present debugger: on_failed # ← s'active uniquement sur cette tâcheNiveau play
Section intitulée « Niveau play »- hosts: webservers debugger: on_failed # ← s'active sur toutes les tasks de ce play tasks: - ...Globalement (variable d'environnement)
Section intitulée « Globalement (variable d'environnement) »ANSIBLE_ENABLE_TASK_DEBUGGER=True ansible-playbook lab.ymlGranularité : task > play > global. La task gagne en cas de conflit.
Valeurs possibles de debugger:
Section intitulée « Valeurs possibles de debugger: »| Valeur | Effet |
|---|---|
always | Ouvre le REPL après chaque tâche (TDD, très lent) |
never | Désactive (default sauf si globalement activé) |
on_failed | Recommandé, REPL uniquement en cas d'échec |
on_unreachable | REPL uniquement si l'host devient unreachable |
on_skipped | REPL si la tâche est skippée (rare) |
Le REPL au runtime
Section intitulée « Le REPL au runtime »Quand une tâche échoue, vous voyez :
TASK [Installer nginx-impossible] ***fatal: [db1.lab]: FAILED! => {"msg": "...nginx-impossible..."}
[db1.lab] TASK: Installer nginx-impossible (debug)>Le prompt (debug)> indique que vous êtes dans le REPL. Tapez help pour la liste.
Les 6 commandes essentielles
Section intitulée « Les 6 commandes essentielles »| Commande | Effet |
|---|---|
p <expr> | Print Python, ex p task, p task.args, p task_vars['x'], p result._result |
task.args['x'] = 'y' | Modifie un argument de la tâche en mémoire |
task_vars['x'] = 'y' | Injecte une variable dans le scope de la tâche |
update_task (u) | Recrée la tâche avec les nouvelles variables/args |
redo (r) | Rejoue la tâche modifiée |
continue (c) / quit (q) | Continuer / abandonner le playbook |
Workflow type, fix d'un mauvais nom de paquet
Section intitulée « Workflow type, fix d'un mauvais nom de paquet »-
La tâche échoue :
fatal: [db1.lab]: FAILED! => {"msg": "Failed to install: nginx-impossible..."}[db1.lab] TASK: Installer nginx-impossible (debug)> -
Inspecter ce qui a été passé :
(debug)> p task.args{'name': 'nginx-impossible', 'state': 'present'} -
Modifier l'argument :
(debug)> task.args['name'] = 'nginx' -
Rejouer :
(debug)> redochanged: [db1.lab] -
Continuer :
(debug)> continueTASK [Tâche suivante] ***...
🔍 Observation : on a fixé un bug sans modifier le YAML ni relancer le playbook. Sur une fleet de 50 hôtes où une seule tâche plante, c'est inestimable.
Workflow, injecter une variable manquante
Section intitulée « Workflow, injecter une variable manquante »- ansible.builtin.copy: dest: "{{ target_dir }}/file.txt" content: "Hello" mode: "0644"Si target_dir n'est pas défini :
fatal: [db1.lab]: FAILED! => {"msg": "...'target_dir' is undefined..."}[db1.lab] TASK: copy (debug)>Au REPL :
(debug)> p task_vars.get('target_dir', 'undefined')'undefined'(debug)> task_vars['target_dir'] = '/tmp'(debug)> update_task(debug)> redochanged: [db1.lab]🔍 Observation : task_vars['x'] = 'y' injecte la variable, update_task (raccourci u) recrée la tâche avec le nouveau scope, puis redo rejoue. Workflow puissant pour résoudre les undefined variable.
⚠️ strategy: linear mandatory en debug
Section intitulée « ⚠️ strategy: linear mandatory en debug »- hosts: webservers strategy: free # ← DANGER avec le débogueur debugger: on_failedAvec strategy: free, pendant que vous êtes au prompt (debug)> sur web1.lab, les tâches de web2.lab continuent à tourner. Race conditions garanties.
Toujours garder strategy: linear (default) en debug pour avoir une pause synchrone sur tous les hosts.
Quand NE PAS utiliser le débogueur
Section intitulée « Quand NE PAS utiliser le débogueur »Le débogueur est interactif. À ne jamais activer dans :
- CI/CD (GitHub Actions, GitLab CI) : pas de stdin → le pipeline freeze indéfiniment.
- AWX / AAP : les jobs n'ont pas de prompt utilisateur.
- Cron / systemd timers : pareil.
- Production : laisser
debugger: on_faileddans un playbook commit en prod = bombe à retardement.
Pour ces contextes, préférer :
-vvv+ logs détaillés (page Verbosité).ANSIBLE_KEEP_REMOTE_FILES=1+ inspection forensic.ansible-navigator replay <artifact.json>(page EE) pour rejouer un échec sans relancer.
Lab pratique
Section intitulée « Lab pratique »Le lab troubleshooting/debugger (labs/troubleshooting/debugger/) couvre les 6 exercices : activer debugger: on_failed, inspecter les vars, modifier les args, injecter une variable, comprendre strategy: linear vs free. Challenge final : fix d'un target_dir manquant au runtime.
À retenir
Section intitulée « À retenir »debugger: on_failedau niveau task ou play, pas en production.pprint accepte n'importe quelle expression Python (vars, args, result).task.args['x'] = ...+redomodifie un argument et rejoue.task_vars['x'] = ...+update_task+redoinjecte une variable manquante.strategy: linearmandatory en debug (race conditions avecfree).- Jamais de débogueur en CI, AAP, cron, ou prod (interactivité requise).