Contactez-nous

Exemple 2 : Exécuter une commande simple avec le module `command` (ex: `uptime`, `df -h`)

Apprenez à utiliser le module `command` d'Ansible pour exécuter des commandes shell basiques comme `uptime` ou `df -h` sur vos noeuds gérés. Idéal pour des actions rapides.

Le module `command` : votre interface directe avec le shell distant

Le module command d'Ansible est l'un des moyens les plus élémentaires pour exécuter des commandes sur vos noeuds gérés. Il est conçu pour lancer des exécutables sans passer par un interpréteur de commandes (shell) sur la machine distante. Cela signifie que les fonctionnalités spécifiques au shell, telles que les redirections (>, <, |), les variables d'environnement (comme $HOME ou $PATH qui seraient interprétées par le shell), ou les métacaractères (globbing, comme * ou ?) ne fonctionneront pas comme attendu. Pour ces cas, le module shell est plus approprié.

Cependant, pour exécuter des commandes simples et autonomes, le module command est souvent plus sûr et plus prévisible, car il évite les complexités et les potentiels problèmes de sécurité liés à l'interprétation par un shell. Il est important de noter que, par défaut, si vous ne spécifiez aucun module avec l'option -m dans une commande Ad-Hoc Ansible, c'est le module command qui est utilisé.

Ce module est particulièrement utile pour des vérifications rapides, la récupération d'informations ponctuelles, ou l'exécution de scripts simples qui ne dépendent pas de l'environnement shell pour leur exécution.

Syntaxe d'utilisation du module `command`

L'utilisation du module command dans une commande Ad-Hoc est directe. Les arguments passés au module via l'option -a (ou --args) représentent la commande exacte que vous souhaitez exécuter sur les noeuds distants.

La syntaxe générale est :

ansible  -m command -a "votre_commande et_ses_arguments" [options_ansible]

Ou, en utilisant le comportement par défaut (omission de -m command) :

ansible  -a "votre_commande et_ses_arguments" [options_ansible]

Quelques points importants concernant les arguments (-a) :

  • La commande et ses arguments doivent être passés comme une seule chaîne de caractères, généralement entre guillemets pour éviter toute interprétation par le shell local de votre noeud de contrôle.
  • Le module command ne traite pas les arguments de la commande comme des paramètres nommés (comme le font d'autres modules Ansible). L'intégralité de la chaîne après -a est considérée comme la commande à exécuter.

Par exemple, si votre fichier d'inventaire myhosts contient un groupe servers :

# myhosts
[servers]
server1 ansible_host=10.0.0.5
server2 ansible_host=10.0.0.6

Pour exécuter la commande hostname sur tous les serveurs de ce groupe :

ansible servers -i myhosts -m command -a "hostname"

Ou plus simplement :

ansible servers -i myhosts -a "hostname"

Exemple concret : vérifier l'uptime et l'espace disque

Voyons deux exemples classiques d'utilisation du module command pour récupérer des informations système de base.

1. Vérifier le temps de fonctionnement (`uptime`)

La commande uptime affiche depuis combien de temps le système est en fonctionnement, le nombre d'utilisateurs connectés et la charge moyenne du système. Pour l'exécuter sur tous les hôtes de votre inventaire par défaut :

ansible all -a "uptime"

La sortie ressemblera à quelque chose comme ceci pour chaque hôte :

server1 | CHANGED | rc=0 >>
 10:30:15 up 5 days, 12:45,  1 user,  load average: 0.00, 0.01, 0.05
server2 | CHANGED | rc=0 >>
 10:30:16 up 22 days,  2:10,  0 users, load average: 0.08, 0.03, 0.01

Notez que la sortie indique CHANGED. C'est parce que le module command, par défaut, ne sait pas si la commande exécutée a modifié l'état du système ou non. Il suppose donc qu'un changement a pu se produire. Nous verrons plus tard comment influencer ce comportement.

2. Vérifier l'utilisation de l'espace disque (`df -h`)

La commande df -h affiche l'utilisation de l'espace disque des systèmes de fichiers montés dans un format lisible par l'homme. Pour l'exécuter sur un groupe spécifique, disons webservers, défini dans un inventaire inventory.ini :

ansible webservers -i inventory.ini -a "df -h"

La sortie pour chaque hôte du groupe webservers listera ses systèmes de fichiers et leur occupation :

web01 | CHANGED | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        20G  5.5G   14G  29% /
tmpfs           990M     0  990M   0% /dev/shm
/dev/sdb1        50G   10G   38G  21% /var/www
web02 | CHANGED | rc=0 >>
Filesystem      Size  Used Avail Use% Mounted on
/dev/mapper/vg0-root   30G  8.2G   20G  30% /
udev            1.9G     0  1.9G   0% /dev
tmpfs           394M  1.1M  393M   1% /run

Ces exemples montrent la simplicité avec laquelle vous pouvez interroger vos machines distantes.

Paramètres optionnels du module `command` : `chdir`, `creates`, `removes`

Bien que les arguments principaux du module command soient la commande elle-même, il accepte quelques paramètres optionnels qui peuvent modifier son comportement et aider à l'idempotence (bien que le module command ne soit intrinsèquement pas idempotent).

  • chdir= : Permet de changer de répertoire de travail sur le noeud distant avant d'exécuter la commande. Utile si la commande doit être exécutée depuis un emplacement spécifique.
  • creates= : Si le fichier ou répertoire spécifié par existe déjà sur le noeud distant, la commande ne sera PAS exécutée. Cela permet d'introduire une forme simple d'idempotence : la commande n'est exécutée que si elle est susceptible de créer ce fichier. L'état rapporté sera skipped si le fichier existe.
  • removes= : Inversement, si le fichier ou répertoire spécifié par N'existe PAS sur le noeud distant, la commande ne sera PAS exécutée. La commande est exécutée uniquement si le fichier qu'elle est censée supprimer existe. L'état rapporté sera skipped si le fichier n'existe pas.

Exemples d'utilisation de ces paramètres :

# Exécuter un script 'setup.sh' depuis '/opt/myapp', seulement si '/opt/myapp/installed.flag' n'existe pas
ansible appservers -m command -a "./setup.sh chdir=/opt/myapp creates=/opt/myapp/installed.flag"

# Supprimer un fichier de cache, seulement si '/tmp/cache_file.dat' existe
ansible all -m command -a "rm /tmp/cache_file.dat removes=/tmp/cache_file.dat"

Dans le premier cas, si /opt/myapp/installed.flag existe, la sortie pour l'hôte sera :

hostname | SKIPPED
{
    "changed": false, 
    "skip_reason": "skipped, since /opt/myapp/installed.flag exists", 
    "skipped": true
}

L'utilisation de creates et removes est une bonne pratique lorsque vous utilisez le module command (ou shell) pour des actions qui ont un effet de bord observable via la présence ou l'absence d'un fichier. Cela permet d'éviter d'exécuter la commande inutilement si l'état désiré est déjà atteint.

Il est crucial de se rappeler que pour la plupart des tâches de gestion de configuration (création de fichiers, gestion de services, installation de paquets), il existe des modules Ansible dédiés qui sont nativement idempotents et offrent une interface plus structurée et plus sûre que command ou shell. Réservez le module command aux situations où aucun module spécifique n'est disponible ou pour des vérifications très simples et ponctuelles.