
block / rescue / always est l'équivalent Ansible de try / catch / finally. Vous groupez des tâches dans un block:, vous fournissez un rescue: qui s'exécute uniquement si une tâche du block échoue, et un always: qui s'exécute toujours (succès ou échec). Cette page explique le pattern, l'ordre d'exécution exact, et les cas pratiques de production : nettoyage, rollback, notification d'échec.
Sans block/rescue/always, la seule façon de gérer une erreur est ignore_errors: true (anti-pattern) ou failed_when: (souvent insuffisant). block/rescue/always est la gestion d'erreur structurée d'Ansible.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- La syntaxe
block: / rescue: / always: - L'ordre d'exécution : block → (rescue si échec) → always
- L'usage de
when:sur un block (propage à toutes les tâches enfants) - Patterns de production : nettoyage, rollback, notification
- La différence avec
ignore_errors:(anti-pattern)
Prérequis
Section intitulée « Prérequis »- Avoir lu Conditions, when et Boucles, loop.
La syntaxe
Section intitulée « La syntaxe »- name: Démo block / rescue / always hosts: db1.lab become: true tasks: - name: Démontrer l'enchaînement block, rescue et always block: - name: Tâche A ansible.builtin.command: /bin/true changed_when: false
- name: Tâche B (peut échouer) ansible.builtin.command: /bin/false changed_when: false
- name: Tâche C (skippée si B échoue) ansible.builtin.command: /bin/true changed_when: false
rescue: - name: Notifier l'erreur ansible.builtin.debug: msg: "Le block a échoué !"
always: - name: Cleanup ansible.builtin.command: /bin/true changed_when: falseL'ordre exact :
Block exécution : Tâche A → succès Tâche B → ÉCHEC ! Block interrompu, on saute le reste Rescue exécuté (Notifier l'erreur)Always exécuté (Cleanup) : toujoursSi toutes les tâches du block réussissent : rescue n'est pas exécuté, always l'est. Si une tâche du block échoue : rescue capture, always est exécuté quoi qu'il arrive.
L'ordre d'exécution complet
Section intitulée « L'ordre d'exécution complet »1. block: ← exécuté en premier - tâche 1 - tâche 2 (si elle échoue : passage direct au rescue) - tâche 3 (skippée si tâche 2 a échoué)2. rescue: ← UNIQUEMENT si une tâche du block a échoué - tâche cleanup d'erreur3. always: ← TOUJOURS exécuté (succès ou échec) - tâche finalisationSi une tâche du rescue elle-même échoue, le play plante (sauf si failed_when: ou un autre rescue parent).
Cas pratique, capture d'échec
Section intitulée « Cas pratique, capture d'échec »Voici l'exemple validé sur le lab ecrire-code-block-rescue-always :
- name: Challenge block rescue always hosts: db1.lab become: true tasks: - name: Déclencher volontairement le rescue block: - name: Tenter une commande qui echoue ansible.builtin.command: /bin/false changed_when: false
rescue: - name: Marqueur rescue ansible.builtin.copy: dest: /tmp/challenge-rescue.txt content: "rescue triggered (block failed)\n" mode: "0644"
always: - name: Marqueur always ansible.builtin.copy: dest: /tmp/challenge-always.txt content: "always executed\n" mode: "0644"PLAY RECAP :
db1.lab : ok=2 changed=2 rescued=1 failed=0rescued=1 = le block a été rescuté. failed=0 = malgré l'échec du /bin/false, le play a terminé avec succès (grâce au rescue).
Patterns de production
Section intitulée « Patterns de production »Pattern 1, Rollback en cas d'échec
Section intitulée « Pattern 1, Rollback en cas d'échec »- name: Migrer la base avec rollback en cas d'échec block: - name: Snapshotter la base ansible.builtin.command: btrfs subvolume snapshot /var/lib/pgsql /var/lib/pgsql/.snap changed_when: true
- name: Lancer la migration ansible.builtin.command: /usr/local/bin/migrate.sh changed_when: true
rescue: - name: Restaurer la base depuis le snapshot ansible.builtin.command: btrfs subvolume rollback /var/lib/pgsql/.snap changed_when: true
- name: Notifier l'équipe ansible.builtin.uri: url: https://slack.example.com/... method: POSTPattern 2, Nettoyage de fichiers temporaires
Section intitulée « Pattern 2, Nettoyage de fichiers temporaires »- name: Travailler dans un répertoire temporaire nettoyé quoi qu'il arrive block: - name: Créer un répertoire temporaire ansible.builtin.tempfile: state: directory register: tmpdir
- name: Travailler dedans ansible.builtin.command: build.sh args: chdir: "{{ tmpdir.path }}" changed_when: true
always: - name: Toujours nettoyer le tempdir when: tmpdir.path is defined ansible.builtin.file: path: "{{ tmpdir.path }}" state: absentalways: garantit que le tempdir est supprimé, même si le command: plante.
Pattern 3, when: sur un block entier
Section intitulée « Pattern 3, when: sur un block entier »- name: Installer la pile applicative sur les distributions RHEL when: ansible_os_family == "RedHat" block: - name: Tâche RHEL/AlmaLinux 1 ansible.builtin.dnf: name: foo
- name: Tâche RHEL/AlmaLinux 2 ansible.builtin.systemd: name: foo state: startedLe when: est propagé à toutes les tâches du block. Plus DRY que de répéter le when: sur chacune.
block vs autres mécanismes d'erreur
Section intitulée « block vs autres mécanismes d'erreur »| Mécanisme | Usage |
|---|---|
block / rescue / always | Gestion d'erreur structurée (try/catch/finally) |
ignore_errors: true | Ignorer une erreur ponctuelle (à éviter) |
failed_when: <expr> | Redéfinir ce qui constitue un échec |
any_errors_fatal: true | Arrêter le play dès la première erreur sur n'importe quel hôte |
block/rescue/always est de loin le plus puissant. Si vous écrivez ignore_errors: true, demandez-vous d'abord si un block ne ferait pas mieux.
Variables et block
Section intitulée « Variables et block »vars:, become:, become_user:, tags:, when: peuvent être posés au niveau du block et propagés aux tâches du block :
- name: Exécuter un groupe de tâches en root become: true vars: pkg_version: "1.2" block: - name: Tâche en root ansible.builtin.dnf: name: foo
- name: Autre tâche en root ansible.builtin.systemd: name: fooPièges fréquents
Section intitulée « Pièges fréquents »| Symptôme | Cause | Fix |
|---|---|---|
rescue: exécuté même quand block réussit | Faux : rescue ne s'exécute QUE si block échoue | Vérifier le code, ce n'est pas le comportement réel |
always: non exécuté quand block échoue | Faux : always s'exécute toujours | Vérifier qu'il y a bien une section always: |
Une tâche qui échoue dans rescue: plante le play | Comportement attendu : si rescue échoue, le play plante | Ajouter un autre rescue parent ou ignore_errors: sur la tâche du rescue |
Variable du block non visible dans rescue: | Faux : vars: du block est visible dans rescue ET always | Vérifier la portée |
failed=0 dans le PLAY RECAP malgré une erreur | Le rescue a capturé, rescued=1 apparaît à la place | Lire correctement le PLAY RECAP |
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »block / rescue / always=try / catch / finallyAnsible.block:: tâches à exécuter ;rescue:: tâches si échec ;always:: tâches toujours exécutées.when:sur un block s'applique à toutes les tâches du block.- Patterns courants : rollback sur échec, cleanup dans always, notification Slack/Teams dans rescue.
- Préférer
block/rescue/alwaysàignore_errors: truedans 99 % des cas.
Mettre en pratique
Section intitulée « Mettre en pratique »Un rollback ne se prouve qu'en provoquant l'échec. Le lab vous fait grouper des tâches dans un block, déclencher volontairement une erreur pour entrer dans rescue et y écrire la compensation, puis vérifier que always nettoie dans les deux cas. Vous y lisez ansible_failed_task pour identifier la tâche qui a cassé, information que le PLAY RECAP seul ne donne pas.
Pour aller plus loin
Section intitulée « Pour aller plus loin »- ignore_errors : la directive que
block/rescueremplace presque toujours, avec ses rares cas légitimes. - any_errors_fatal : le cran au-dessus, quand une erreur sur un seul hôte doit arrêter tout le play.
- Quiz Écrire du code : 30 questions pour situer votre niveau sur la gestion d'erreurs et le reste du module.