Compte rendu de TP : Variables enregistrées et exécution de commandes (Atelier 15)¶
Objectif
Apprendre à exécuter des commandes système classiques à l'intérieur d'un playbook, capturer leur résultat avec la directive register, et l'afficher. Forcer l'idempotence de ces commandes de lecture seules avec changed_when: false.
Durée
~25 minutes
Objectif du TP¶
L'objectif de cet atelier est d'apprendre à exécuter des commandes système classiques (qui ne disposent pas de modules ansible dédiés) à l'intérieur d'un playbook, de capturer leur résultat grâce à la directive register, et de l'afficher. Nous apprenons également à forcer l'idempotence de ces commandes de lecture seules avec la directive changed_when: false.
1. Préparation de l'environnement¶
Après avoir démarré les machines de l'atelier (vagrant up) et nous être connectés au nœud de contrôle (vagrant ssh ansible), nous chargeons l'environnement du projet via direnv :
Nous nous plaçons ensuite dans le répertoire dédié à la création de nos playbooks :
2. Affichage des informations du noyau (kernel.yml)¶
Notre premier objectif est d'exécuter la commande uname -a sur l'ensemble de notre parc, de stocker le résultat, puis de l'afficher de deux manières différentes.
Variante 1 : Affichage avec le paramètre msg¶
Nous créons un premier fichier kernel.yml en utilisant le module command et en formatant l'affichage avec le paramètre msg du module debug :
---
# kernel.yml
- hosts: all
gather_facts: false
tasks:
- name: Get kernel information
command: uname -a
register: kernel_info
changed_when: false
- name: Display kernel info (using msg)
debug:
msg: "Informations du noyau : {{ kernel_info.stdout }}"
...
Note : La directive changed_when: false est cruciale ici. Elle indique à ansible que la commande uname -a ne fait que lire des informations sans altérer le système, ce qui évite de fausser les statistiques de modification (le statut restera sur ok au lieu de changed).
Exécution du playbook :

Comme l'illustre la capture ci-dessus (img01.png), la commande renvoie les informations spécifiques au noyau de chaque distribution (Rocky, Debian, SUSE) de manière formatée. Le récapitulatif (PLAY RECAP) confirme que changed=0, validant notre directive d'idempotence.
Variante 2 : Affichage avec le paramètre var¶
Le module debug propose une syntaxe alternative plus directe avec le paramètre var, qui n'utilise pas les doubles accolades {{ }}. Nous adaptons la tâche d'affichage de notre playbook :
Exécution de cette seconde variante :

L'image ci-dessus (img02.png) montre que cette approche retourne un format de type clé/valeur ("kernel_info.stdout": "Linux..."), ce qui est particulièrement utile et lisible pour le débogage de structures complexes lors du développement de playbooks.
3. Comptage des paquets RPM (packages.yml)¶
Le deuxième exercice consiste à compter le nombre de paquets RPM installés sur nos machines compatibles (Rocky Linux et SUSE Linux).
Détail technique : La commande demandée (rpm -qa | wc -l) utilise un tube (pipe |). Le module ansible command ne gérant pas les opérateurs shell (comme |, >, <), il est obligatoire d'utiliser le module shell pour cette tâche.
Nous créons le fichier packages.yml en ciblant spécifiquement les hôtes rocky et suse :
---
# packages.yml
- hosts: rocky, suse
gather_facts: false
tasks:
- name: Count installed RPM packages
shell: rpm -qa | wc -l
register: rpm_count
changed_when: false
- name: Display package count
debug:
msg: "Nombre total de paquets RPM installés : {{ rpm_count.stdout }}"
...
Exécution du playbook :

Le résultat (img03.png) affiche l'exécution ciblée sur les nœuds Rocky et SUSE. La commande remonte avec succès la valeur numérique exacte calculée sur chaque système : 642 paquets pour Rocky Linux, et 504 paquets pour SUSE Linux. Encore une fois, la tâche est marquée en ok sans altérer le système (changed=0).
4. Nettoyage de l'environnement¶
L'atelier étant terminé et le comportement des variables enregistrées parfaitement assimilé, nous quittons le Control Host et procédons à la suppression des machines virtuelles :
Je retiens
registercapture le résultat d'une tâche dans une variable réutilisable (.stdout,.stderr,.rc...).changed_when: falseforce le statutokpour les commandes en lecture seule (pas de modification système).debugavecmsgformate l'affichage librement ;debugavecvardonne un format clé/valeur brut (utile pour le debug).- Le module
shellest nécessaire dès qu'un pipe (|) ou une redirection est utilisée, contrairement àcommand(cf. Workshop 05).
Cheatsheet¶
| Symptôme | Cause probable | Correction |
|---|---|---|
kernel_info.stdout → undefined variable |
register: oublié sur la tâche qui produit la sortie |
Ajouter register: kernel_info sur la tâche command: |
Sortie sur plusieurs lignes concaténée dans .stdout |
.stdout est une chaîne unique |
Utiliser .stdout_lines qui renvoie une liste, plus pratique avec debug: var=... |
rpm -qa \| wc -l → échec avec le module command |
command n'interprète pas le pipe |
Passer au module shell (cf. Workshop 05) |
La tâche reste marquée changed alors qu'elle ne modifie rien |
command / shell sont changed par défaut |
Ajouter changed_when: false (ou une condition basée sur .rc / .stdout) |
failed: task ... sans message clair |
Le code retour n'est pas 0 et failed_when n'est pas défini |
Utiliser ignore_errors: true pour déboguer, puis affiner avec failed_when: kernel_info.rc != 0 |
La variable register n'est pas accessible dans une autre play |
Les register ont une portée par hôte et par play ; elles ne sont pas partagées entre plays |
Utiliser set_fact pour promouvoir la valeur si besoin d'une persistance inter-play |
Sources (principales)¶
- Docs
ansibleRegistering variables - Docs
ansibleReturn values (.stdout,.stderr,.rc,.stdout_lines) - Docs
ansiblechanged_when&failed_when - Docs
ansibleansible.builtin.commandmodule - Docs
ansibleansible.builtin.shellmodule - Docs
ansibleansible.builtin.debugmodule - Docs
ansibleset_fact(promouvoir un register en fact persistant) - Docs
ansibleignore_errorset gestion d'erreur
Précédent : Variables Suite : Facts + Implicit Vars