Comment afficher la sortie d'un script dans un playbook Ansible

AnsibleBeginner
Pratiquer maintenant

Introduction

Ansible est un outil d'automatisation puissant qui aide les administrateurs système et les développeurs à gérer l'infrastructure de manière efficace. Lors de l'exécution de scripts ou de commandes via des playbooks Ansible, il est souvent crucial de capturer et d'afficher leur sortie à des fins de surveillance et de dépannage.

Dans ce laboratoire pratique, vous apprendrez comment afficher efficacement la sortie des scripts dans vos playbooks Ansible. Nous commencerons par les bases de la structure d'un playbook Ansible, puis explorerons diverses techniques pour capturer et afficher les sorties de commandes, et enfin, nous aborderons des méthodes avancées pour formater et filtrer les données de sortie.

À la fin de ce laboratoire, vous aurez une expérience pratique avec différentes approches pour gérer la sortie des scripts dans Ansible, ce qui vous permettra de créer des flux de travail d'automatisation plus informatifs et plus faciles à déboguer.

Configuration de votre premier playbook Ansible

Avant de pouvoir explorer comment afficher la sortie des scripts, nous devons configurer un environnement Ansible de base et créer notre premier playbook.

Installation d'Ansible

Commençons par nous assurer qu'Ansible est installé sur notre système :

sudo apt update
sudo apt install -y ansible

Cette commande installera Ansible sur votre système Ubuntu. Une fois l'installation terminée, vérifiez-la en vérifiant la version d'Ansible :

ansible --version

Vous devriez voir une sortie similaire à la suivante, ce qui confirme qu'Ansible est correctement installé :

ansible [core 2.12.x]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/labex/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/labex/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.x (default, Mar 14 2023, 14:50:41) [GCC 11.3.0]
  jinja version = 3.0.3
  libyaml = True

Comprendre l'inventaire Ansible

Ansible doit savoir à quels hôtes se connecter. Pour ce laboratoire, nous utiliserons un simple fichier d'inventaire qui inclut uniquement la machine locale.

Créez un répertoire pour notre projet Ansible :

mkdir -p ~/project/ansible-lab
cd ~/project/ansible-lab

Maintenant, créez un fichier d'inventaire nommé inventory.ini :

echo "localhost ansible_connection=local" > inventory.ini

Ce fichier d'inventaire indique à Ansible d'exécuter les commandes sur la machine locale sans utiliser SSH.

Création de votre premier playbook

Maintenant, créons un playbook Ansible de base. Dans le WebIDE, créez un nouveau fichier appelé first_playbook.yml dans le répertoire ~/project/ansible-lab avec le contenu suivant :

---
- name: My First Ansible Playbook
  hosts: localhost
  gather_facts: yes

  tasks:
    - name: Display a simple message
      debug:
        msg: "Hello from Ansible!"

    - name: Display system information
      debug:
        msg: "You are running {{ ansible_distribution }} {{ ansible_distribution_version }}"

Ce playbook simple comporte deux tâches :

  1. Afficher un simple message de salutation
  2. Afficher des informations sur le système d'exploitation que vous utilisez

Exécutons ce playbook pour voir comment il fonctionne :

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini first_playbook.yml

Vous devriez voir une sortie similaire à celle-ci :

PLAY [My First Ansible Playbook] *********************************************************

TASK [Gathering Facts] *******************************************************************
ok: [localhost]

TASK [Display a simple message] **********************************************************
ok: [localhost] => {
    "msg": "Hello from Ansible!"
}

TASK [Display system information] ********************************************************
ok: [localhost] => {
    "msg": "You are running Ubuntu 22.04"
}

PLAY RECAP *******************************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Cette sortie montre :

  • Le playbook s'est exécuté avec succès
  • Toutes les tâches se sont terminées avec le statut "ok"
  • La sortie de chaque tâche de débogage est affichée

Maintenant que nous avons un playbook de base qui fonctionne, nous pouvons explorer comment exécuter des scripts et afficher leur sortie plus en détail.

Exécution de scripts et capture de la sortie

Maintenant que nous avons configuré un environnement Ansible de base, explorons comment exécuter des scripts et capturer leur sortie à l'aide des modules command et shell.

La différence entre les modules Command et Shell

Ansible fournit deux modules principaux pour l'exécution de commandes :

  • command : Exécute une commande sur un nœud distant sans passer par un shell, ce qui signifie que les opérateurs shell tels que |, >, <, et & ne fonctionnent pas.
  • shell : Exécute une commande via un shell, permettant l'utilisation d'opérateurs shell et de variables d'environnement.

Création d'un script simple à exécuter

Tout d'abord, créons un script shell simple que nous pourrons exécuter avec Ansible. Créez un fichier nommé system_info.sh dans votre répertoire ~/project/ansible-lab :

cd ~/project/ansible-lab

Dans le WebIDE, créez le fichier avec le contenu suivant :

#!/bin/bash

echo "=== System Information ==="
echo "Hostname: $(hostname)"
echo "Kernel Version: $(uname -r)"
echo "CPU Info: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d':' -f2 | xargs)"
echo "Memory Info: $(free -h | grep Mem | awk '{print $2 " total, " $3 " used, " $4 " free"}')"
echo "Disk Usage: $(df -h / | grep / | awk '{print $5 " of " $2 " used"}')"

Rendez le script exécutable :

chmod +x ~/project/ansible-lab/system_info.sh

Maintenant, exécutons ce script manuellement pour voir quelle sortie il produit :

./system_info.sh

Vous devriez voir une sortie similaire à :

=== System Information ===
Hostname: labex-xxxxxxxx
Kernel Version: 5.15.0-xx-generic
CPU Info: Intel(R) Xeon(R) xxxxxx
Memory Info: 8.0G total, 1.2G used, 5.8G free
Disk Usage: 15% of 50G used

Exécution du script avec Ansible

Maintenant, créons un nouveau playbook qui exécutera ce script et capturera sa sortie. Créez un fichier nommé script_output.yml dans votre répertoire ~/project/ansible-lab :

---
- name: Run Script and Capture Output
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run system info script
      command: ./system_info.sh
      register: script_result

    - name: Display script output
      debug:
        msg: "{{ script_result.stdout }}"

Ce playbook fait deux choses :

  1. Exécute notre script system_info.sh en utilisant le module command
  2. Stocke la sortie dans une variable appelée script_result en utilisant le mot-clé register
  3. Affiche la sortie capturée en utilisant le module debug

Exécutons ce playbook :

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini script_output.yml

Vous devriez voir une sortie similaire à :

PLAY [Run Script and Capture Output] ***************************************************

TASK [Run system info script] ***********************************************************
changed: [localhost]

TASK [Display script output] ************************************************************
ok: [localhost] => {
    "msg": "=== System Information ===\nHostname: labex-xxxxxxxx\nKernel Version: 5.15.0-xx-generic\nCPU Info: Intel(R) Xeon(R) xxxxxx\nMemory Info: 8.0G total, 1.2G used, 5.8G free\nDisk Usage: 15% of 50G used"
}

PLAY RECAP *****************************************************************************
localhost                  : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Remarquez comment la sortie apparaît sous forme d'une seule chaîne avec des caractères de nouvelle ligne (\n). Améliorons l'affichage dans la section suivante.

Comprendre la variable Register

Le mot-clé register crée une variable qui contient plusieurs attributs, et pas seulement la sortie de la commande. Créons un nouveau playbook pour explorer ces attributs.

Créez un fichier nommé register_details.yml dans votre répertoire ~/project/ansible-lab :

---
- name: Explore Register Variable
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run system info script
      command: ./system_info.sh
      register: script_result

    - name: Display all register properties
      debug:
        var: script_result

    - name: Display just stdout
      debug:
        var: script_result.stdout

    - name: Display stdout as a list of lines
      debug:
        var: script_result.stdout_lines

Exécutez ce playbook :

ansible-playbook -i inventory.ini register_details.yml

Vous verrez une sortie plus détaillée qui montre toutes les propriétés de la variable script_result, notamment :

  • stdout : La sortie standard sous forme d'une seule chaîne
  • stderr : L'erreur standard (le cas échéant)
  • rc : Le code de retour (0 signifie succès)
  • stdout_lines : La sortie standard divisée en une liste de lignes

La dernière tâche est particulièrement utile car elle formate la sortie sous forme de liste de lignes, ce qui la rend beaucoup plus lisible.

Techniques avancées de gestion de la sortie

Maintenant que nous comprenons les bases de la capture de la sortie des scripts, explorons des techniques plus avancées pour gérer et afficher la sortie dans les playbooks Ansible.

Gestion des erreurs de script

Lors de l'exécution de scripts, il est important de gérer correctement les conditions d'erreur. Ansible marque une tâche comme ayant échoué si la commande renvoie un code de sortie différent de zéro. Créons un playbook qui démontre la gestion des erreurs.

Créez un fichier nommé error_handling.yml dans votre répertoire ~/project/ansible-lab :

---
- name: Handling Script Errors
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run a command that might fail
      command: ls /nonexistent_directory
      register: cmd_result
      ignore_errors: yes

    - name: Show error message if command failed
      debug:
        msg: "Command failed with error: {{ cmd_result.stderr }}"
      when: cmd_result.rc != 0

    - name: Show success message if command succeeded
      debug:
        msg: "Command succeeded with output: {{ cmd_result.stdout }}"
      when: cmd_result.rc == 0

Dans ce playbook :

  1. Nous tentons de lister un répertoire qui n'existe pas
  2. Nous utilisons ignore_errors: yes pour empêcher le playbook de s'arrêter si la commande échoue
  3. Nous vérifions le code de retour (cmd_result.rc) pour déterminer si la commande a réussi ou échoué
  4. Nous affichons les messages appropriés en fonction du résultat

Exécutons ce playbook :

cd ~/project/ansible-lab
ansible-playbook -i inventory.ini error_handling.yml

Vous devriez voir une sortie similaire à :

PLAY [Handling Script Errors] ***********************************************************

TASK [Run a command that might fail] ***************************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["ls", "/nonexistent_directory"], "delta": "0:00:00.003398", "end": "2023-09-15 12:34:56.789012", "msg": "non-zero return code", "rc": 2, "start": "2023-09-15 12:34:56.785614", "stderr": "ls: cannot access '/nonexistent_directory': No such file or directory", "stderr_lines": ["ls: cannot access '/nonexistent_directory': No such file or directory"], "stdout": "", "stdout_lines": []}
...ignoring

TASK [Show error message if command failed] *********************************************
ok: [localhost] => {
    "msg": "Command failed with error: ls: cannot access '/nonexistent_directory': No such file or directory"
}

TASK [Show success message if command succeeded] ****************************************
skipping: [localhost]

PLAY RECAP *******************************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=1

Remarquez que malgré l'échec de la commande, le playbook continue de s'exécuter et affiche le message d'erreur.

Formatage de la sortie multiligne

Créons un script plus complexe qui génère une sortie multiligne, puis formatons-la correctement dans notre playbook.

Créez un fichier nommé package_info.sh dans votre répertoire ~/project/ansible-lab :

#!/bin/bash

echo "TOP 5 LARGEST INSTALLED PACKAGES"
echo "================================"
dpkg-query -W -f='${Installed-Size}\t${Package}\n' | sort -n -r | head -5

Rendez-le exécutable :

chmod +x ~/project/ansible-lab/package_info.sh

Maintenant, créez un playbook pour exécuter ce script et formater correctement la sortie. Créez un fichier nommé formatted_output.yml :

---
- name: Format Script Output
  hosts: localhost
  gather_facts: no

  tasks:
    - name: Run package info script
      shell: ./package_info.sh
      register: pkg_info

    - name: Display raw output
      debug:
        msg: "{{ pkg_info.stdout }}"

    - name: Display formatted output with a title
      debug:
        msg: |
          Below is the package information:
          --------------------------------
          {% for line in pkg_info.stdout_lines %}
          {{ line }}
          {% endfor %}
          --------------------------------
          Total lines: {{ pkg_info.stdout_lines | length }}

Ce playbook :

  1. Exécute notre script package_info.sh
  2. Affiche la sortie brute
  3. Utilise un modèle Jinja2 pour formater la sortie avec un titre et un pied de page

Exécutons-le :

ansible-playbook -i inventory.ini formatted_output.yml

Vous devriez voir une sortie correctement formatée :

PLAY [Format Script Output] ***********************************************************

TASK [Run package info script] ********************************************************
changed: [localhost]

TASK [Display raw output] *************************************************************
ok: [localhost] => {
    "msg": "TOP 5 LARGEST INSTALLED PACKAGES\n================================\n112233\tsome-large-package\n99887\tanother-package\n...\n"
}

TASK [Display formatted output with a title] ******************************************
ok: [localhost] => {
    "msg": "Below is the package information:\n--------------------------------\nTOP 5 LARGEST INSTALLED PACKAGES\n================================\n112233\tsome-large-package\n99887\tanother-package\n...\n--------------------------------\nTotal lines: 7"
}

PLAY RECAP ****************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Affichage conditionnel de la sortie

Parfois, vous ne souhaitez afficher la sortie que dans certaines conditions, par exemple lors de l'exécution en mode verbeux. Voyons comment faire cela.

Créez un fichier nommé conditional_output.yml dans votre répertoire ~/project/ansible-lab :

---
- name: Conditional Output Display
  hosts: localhost
  gather_facts: yes

  tasks:
    - name: Get disk usage information
      shell: df -h
      register: disk_info

    - name: Display disk usage (always shown)
      debug:
        msg: "{{ disk_info.stdout_lines[0:2] }}"

    - name: Display detailed disk usage (only in verbose mode)
      debug:
        msg: "{{ disk_info.stdout_lines }}"
        verbosity: 1

Dans ce playbook :

  1. Nous capturons les informations d'utilisation du disque
  2. Nous affichons toujours un résumé (deux premières lignes)
  3. Nous affichons les détails complets uniquement lors de l'exécution en mode verbeux (avec l'option -v)

Exécutons-le d'abord en mode normal :

ansible-playbook -i inventory.ini conditional_output.yml

Maintenant, exécutons-le en mode verbeux :

ansible-playbook -i inventory.ini conditional_output.yml -v

Vous remarquerez qu'en mode verbeux, vous obtenez les informations complètes sur l'utilisation du disque, tandis qu'en mode normal, vous ne voyez que le résumé.

Cette technique est utile pour masquer par défaut une sortie potentiellement sensible ou accablante, tout en la rendant disponible en cas de besoin pour le débogage.

Résumé

Dans ce lab, vous avez appris diverses techniques pour capturer et afficher la sortie de scripts dans les playbooks Ansible :

  1. Vous avez configuré un environnement Ansible de base et créé votre premier playbook
  2. Vous avez appris à exécuter des scripts en utilisant les modules command et shell
  3. Vous avez capturé la sortie des scripts en utilisant la directive register
  4. Vous avez affiché la sortie en utilisant le module debug dans différents formats
  5. Vous avez géré les conditions d'erreur et mis en œuvre l'affichage conditionnel de la sortie
  6. Vous avez appliqué des techniques de formatage pour rendre la sortie plus lisible

Ces compétences vous permettent de créer des playbooks Ansible plus informatifs qui fournissent des commentaires clairs pendant l'exécution. Cette visibilité est cruciale à la fois pour la surveillance des processus automatisés et pour le dépannage en cas de problèmes.

En tirant parti de ces techniques de gestion de la sortie, vous pouvez construire des flux de travail d'automatisation plus robustes qui non seulement exécutent des tâches, mais communiquent également clairement ce qui se passe à chaque étape. Cela rend votre automatisation plus transparente et plus facile à maintenir, en particulier lorsque vous travaillez en équipe ou avec une infrastructure complexe.