Aller au contenu
Infrastructure as Code medium

Commandes ad-hoc Ansible : modules, patterns d'hôtes et quand basculer en playbook

11 min de lecture

Logo Ansible

Une commande ad-hoc Ansible exécute un module unique sur un pattern d’hôtes, sans écrire de playbook. C’est l’outil parfait pour les opérations one-shot : tester la connectivité, vérifier la version d’un paquet, redémarrer un service sur un sous-ensemble de la fleet, copier un fichier ponctuel. Les commandes ad-hoc constituent un objectif explicite de l’examen RHCE EX294 — vous devez savoir les écrire à la volée sans hésiter. Cette page couvre la syntaxe, les modules essentiels avec sorties réelles, les patterns d’hôtes, et les critères pour basculer en playbook.

  • Comprendre la syntaxe ansible PATTERN -m MODULE -a "ARGS" et chaque composant ;
  • Lancer les modules de base : ping, setup, command, shell, dnf, service, copy, file ;
  • Cibler des hôtes avec les patterns : groupes, wildcards, intersections, exclusions ;
  • Reconnaître les trois statuts dans la sortie (SUCCESS, CHANGED, FAILED) ;
  • Décider quand une opération doit basculer en playbook (idempotence stricte, multi-tâches, traçabilité).
Fenêtre de terminal
ansible PATTERN -m MODULE [-a "ARGS"] [OPTIONS]
ComposantRôleExemple
PATTERNCible un ou plusieurs hôtesall, web1.lab, webservers, web*
-m MODULEModule à exécuterping, setup, dnf, service, copy, file
-a "ARGS"Arguments du module (clé=valeur)name=nginx state=present
OPTIONSOptions Ansible--check, --diff, -b (become), -K (ask sudo pwd)

Si vous omettez -m, Ansible utilise par défaut le module command (ansible all -a 'uptime' est équivalent à ansible all -m command -a 'uptime'). Mais soyez explicite — vous gagnerez en clarté.

Fenêtre de terminal
ansible all -m ping
web1.lab | SUCCESS => {
"changed": false,
"ping": "pong"
}
db1.lab | SUCCESS => {
"changed": false,
"ping": "pong"
}
web2.lab | SUCCESS => {
"changed": false,
"ping": "pong"
}
control-node.lab | SUCCESS => {
"changed": false,
"ping": "pong"
}

SUCCESS + changed: false : la chaîne fonctionne et rien n’a été modifié.

Le module setup affiche les centaines de variables que la phase gather_facts collecte au début de chaque play. Pratique pour vérifier la valeur d’un fact :

Fenêtre de terminal
ansible web1.lab -m setup -a 'filter=ansible_distribution*'
web1.lab | SUCCESS => {
"ansible_facts": {
"ansible_distribution": "AlmaLinux",
"ansible_distribution_file_parsed": true,
"ansible_distribution_file_path": "/etc/redhat-release",
"ansible_distribution_file_variety": "RedHat",
"ansible_distribution_major_version": "10",
"ansible_distribution_release": "Heliotrope Lion",
"ansible_distribution_version": "10.1"
},
"changed": false
}

Le filter= accepte un wildcard glob. Sans filtre, vous récupérez plusieurs centaines de lignes de facts.

Fenêtre de terminal
ansible webservers -m command -a 'uptime'
web1.lab | CHANGED | rc=0 >>
14:40:14 up 6 min, 2 users, load average: 0.06, 0.12, 0.06
web2.lab | CHANGED | rc=0 >>
14:40:15 up 6 min, 2 users, load average: 0.06, 0.10, 0.04

Statut CHANGED parce que command est non-idempotent par défaut. Le rc=0 confirme l’exit code zéro. Pas de pipe, pas de redirection (>), pas de variable d’environnement — c’est le rôle de shell.

Fenêtre de terminal
ansible webservers -m shell -a 'df -h / | tail -1'
web1.lab | CHANGED | rc=0 >>
/dev/vda4 8.8G 1.1G 7.8G 12% /
web2.lab | CHANGED | rc=0 >>
/dev/vda4 8.8G 1.1G 7.8G 12% /

shell accepte les pipes, redirections, et variables d’environnement. À utiliser uniquement quand command ne suffit pas — shell est un vecteur d’injection si la valeur vient d’une variable mal contrôlée.

Fenêtre de terminal
ansible db1.lab -m dnf -a 'name=tree state=present' --check
db1.lab | CHANGED => {
"changed": true,
"msg": "Check mode: No changes made, but would have if not in check mode",
"rc": 0,
"results": [
"Installed: tree-2.1.0-8.el10.x86_64"
]
}

L’option --check (dry-run) montre ce qui serait fait sans appliquer le changement. C’est la combinaison parfaite pour valider une commande risquée avant de la lancer pour de vrai.

service — gérer les services systemd (idempotent)

Section intitulée « service — gérer les services systemd (idempotent) »
Fenêtre de terminal
ansible web1.lab -m service -a 'name=firewalld state=started'
web1.lab | SUCCESS => {
"changed": false,
"name": "firewalld",
"state": "started",
...
}

changed: false parce que firewalld est déjà démarré (le playbook de préparation l’a fait). service est idempotent : il ne tente l’action que si l’état réel diverge de l’état désiré.

copy — copier un fichier (idempotent par checksum)

Section intitulée « copy — copier un fichier (idempotent par checksum) »
Fenêtre de terminal
echo "test ansible 2026" > /tmp/ansible-test.txt
ansible web1.lab -m copy -a 'src=/tmp/ansible-test.txt dest=/tmp/ansible-test.txt mode=0644'

Premier run :

web1.lab | CHANGED => {
"changed": true,
"checksum": "6e8652783ec319763ffa93599d00443fba131901",
"dest": "/tmp/ansible-test.txt",
"mode": "0644",
...
}

Second run immédiat :

web1.lab | SUCCESS => {
"changed": false,
"checksum": "6e8652783ec319763ffa93599d00443fba131901",
"dest": "/tmp/ansible-test.txt",
"mode": "0644",
...
}

SUCCESS + changed: false : Ansible a comparé le checksum SHA-1 local et distant, ils sont identiques, aucun transfert n’a eu lieu. C’est l’idempotence par checksum.

file — gérer les permissions et les chemins (idempotent)

Section intitulée « file — gérer les permissions et les chemins (idempotent) »
Fenêtre de terminal
ansible web1.lab -m file -a 'path=/tmp/ansible-test.txt state=absent'
web1.lab | CHANGED => {
"changed": true,
"path": "/tmp/ansible-test.txt",
"state": "absent"
}

Au second run, le fichier est déjà absent → changed: false. Le module file couvre aussi les permissions (mode, owner, group), les liens symboliques (state=link) et la création de répertoires (state=directory).

PatternCible
allTous les hôtes de l’inventaire
web1.labUn seul hôte par son nom exact
webserversTous les hôtes du groupe webservers
webservers:dbserversUnion : tous les hôtes des deux groupes
webservers:&rhce_labIntersection : hôtes dans webservers ET dans rhce_lab
webservers:!web1.labExclusion : tous les webservers SAUF web1.lab
web*Wildcard : tout hôte commençant par web
web*:!*.localCombinaison : web* SAUF *.local

Exemple concret — appliquer un patch sur tous les webservers sauf un :

Fenêtre de terminal
ansible 'webservers:!web1.lab' -m dnf -a 'name=* state=latest' -b

L’option -b active become (sudo). Le * côté name= met tous les paquets à jour.

StatutCouleurSignification
SUCCESSvertModule idempotent, aucun changement
CHANGEDjauneModule a appliqué un changement réel
FAILEDrougeModule a échoué (rc != 0, exception, etc.)
UNREACHABLErougeHôte injoignable en SSH

SUCCESS + changed: false est le signal qu’un second passage n’aurait rien à faire — c’est la preuve d’idempotence au niveau ad-hoc.

L’ad-hoc atteint ses limites dès que l’opération devient :

  • Multi-tâches : enchaîner installation + configuration + démarrage de service. Un playbook gère la séquence et arrête tout en cas d’erreur intermédiaire.
  • Conditionnelle : « installer nginx si la distribution est RedHat ». Un when: dans un play est plus propre qu’un script qui appelle ansible plusieurs fois.
  • Traçable : un playbook YAML versionné dans Git documente l’opération, sa relance est reproductible. Une commande ad-hoc dans un terminal est volatile.
  • Idempotente avec variables : ad-hoc accepte -a "name={{ var }}" mais sans inventaire de variables, ça devient vite illisible. Variables, vars_files et group_vars sont la zone du playbook.

Règle pratique : plus de 3 commandes ad-hoc consécutives sur la même cible = il est temps d’écrire un playbook.

SymptômeCauseFix
module not found ou silenceMauvais nom de module ou collection non installéeansible-doc -l | grep <nom> ; ansible-galaxy collection install <fqcn>
Pipes (|) and redirections require a shellcommand reçoit un pipe alors qu’il ne supporte pasBascule en -m shell (et seulement si nécessaire)
changed=true à chaque run sur command/shellModules non idempotents par natureAjouter creates: ou removes: ; mieux : utiliser le module idempotent dédié (dnf, service, file)
--ask-pass demandé alors que la clé est OKAnsible n’a pas trouvé la cléVérifier ansible.cfg (private_key_file) ou poser ansible_ssh_private_key_file dans l’inventaire
  • La syntaxe ansible PATTERN -m MODULE -a "ARGS" est l’outil principal pour les opérations one-shot sur une fleet.
  • Les modules essentiels sont ping, setup, command, shell, dnf, service, copy, file — à connaître par cœur pour la RHCE.
  • Les patterns d’hôtes combinent groupes, wildcards, intersections (&) et exclusions (!).
  • SUCCESS + changed: false = idempotence ; CHANGED = action réelle ; FAILED = à investiguer.
  • Bascule en playbook dès que l’opération est multi-tâches, conditionnelle, traçable ou paramétrée.
  • L’option --check est le mode dry-run universel pour valider sans appliquer.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn