Aller au contenu
English
English
Infrastructure as Code medium

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

50 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é.

Huit modules suffisent à couvrir la quasi-totalité des besoins ponctuels, et ils se retrouvent tels quels dans les playbooks. Deux servent à observer la machine, deux à y exécuter une commande, quatre à converger un état, paquets, services, fichiers et permissions. Ce découpage vaut aussi pour les playbooks. Ce sont ces derniers qui sont idempotents.

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.

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é.

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.

Deux de ces quatre pièges viennent du choix du module : une commande brute là où un module dédié existe, ou un module de commande simple à qui l'on demande une construction de shell. Les deux autres relèvent de l'environnement, un module absent faute de collection et une clé que rien ne désigne dans la configuration.

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

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

6 questions
6 min.
70% requis

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

  • 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.
  • Premier playbook : la bascule annoncée ici, avec le même besoin écrit en YAML et rejouable.
  • Debug premières erreurs : décode les messages qui bloquent une commande ad-hoc, Permission denied en tête.
  • Plays et tasks : l'anatomie complète d'un play, une fois que la ligne de commande ne suffit plus.

Ce site vous est utile ?

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

Je maintiens ce site gratuitement, sans publicité, sans profilage et sans compte à créer. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn