Comment Capturer la Sortie d'un Script Exécuté par Ansible

AnsibleBeginner
Pratiquer maintenant

Introduction

Ansible est un outil d'automatisation informatique largement utilisé qui simplifie la gestion des infrastructures complexes et des déploiements d'applications. Dans ce tutoriel, nous allons explorer comment capturer la sortie des scripts exécutés via les playbooks Ansible. Cette capacité est essentielle pour la surveillance, le débogage et l'analyse des résultats de vos tâches d'automatisation. À la fin de ce lab, vous comprendrez diverses techniques pour capturer et utiliser la sortie des scripts dans vos flux de travail Ansible.

Configuration de l'environnement Ansible

Avant de pouvoir commencer à capturer les sorties de scripts avec Ansible, nous devons configurer un environnement Ansible de base. Cela inclut la création de la structure de répertoire et des fichiers de configuration nécessaires.

Comprendre les bases d'Ansible

Ansible fonctionne en se connectant aux hôtes cibles et en poussant de petits programmes appelés modules. Ces modules sont exécutés sur les hôtes cibles et supprimés une fois l'exécution terminée. Ansible est sans agent (agent-less), ce qui signifie que vous n'avez pas besoin d'installer de logiciel spécial sur les nœuds gérés.

Commençons par créer un répertoire de projet et les fichiers Ansible nécessaires :

mkdir -p ~/project/ansible-output-demo/scripts
cd ~/project/ansible-output-demo

Maintenant, créons un simple fichier d'inventaire. Dans Ansible, le fichier d'inventaire définit les hôtes et les groupes d'hôtes sur lesquels les commandes, les modules et les tâches d'un playbook opèrent.

Créez un fichier d'inventaire en utilisant l'éditeur de code :

  1. Cliquez sur le menu "File" dans le coin supérieur gauche de l'IDE
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom inventory dans le répertoire ~/project/ansible-output-demo

Ajoutez le contenu suivant au fichier inventory :

[local]
localhost ansible_connection=local

Ce fichier d'inventaire spécifie que nous allons exécuter Ansible sur la machine locale.

Ensuite, créons un script simple qui générera une sortie que nous pourrons capturer. Ce script va :

  1. Afficher des informations système
  2. Générer une sortie standard
  3. Générer une sortie d'erreur standard

Créez un nouveau fichier dans le répertoire scripts nommé info.sh :

  1. Cliquez sur le menu "File"
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom scripts/info.sh dans le répertoire ~/project/ansible-output-demo

Ajoutez le contenu suivant au fichier info.sh :

#!/bin/bash

## Print system information
echo "=== System Information ==="
echo "Hostname: $(hostname)"
echo "Date: $(date)"
echo "Kernel: $(uname -r)"
echo "Memory:"
free -h

## Generate some standard output
echo "=== Standard Output ==="
echo "This is standard output"
echo "Hello from the script!"

## Generate some standard error
echo "=== Standard Error ===" >&2
echo "This is standard error" >&2
echo "An example error message" >&2

## Exit with a specific code
exit 0

Maintenant, rendons le script exécutable :

chmod +x ~/project/ansible-output-demo/scripts/info.sh

Exécutons le script directement pour voir quelle sortie il produit :

~/project/ansible-output-demo/scripts/info.sh

Vous devriez voir une sortie contenant des informations système, des messages de sortie standard et des messages d'erreur standard.

Nous avons maintenant notre environnement de base configuré. Dans l'étape suivante, nous allons créer un playbook Ansible pour exécuter ce script et capturer sa sortie.

Capture de sortie de base avec Ansible

Maintenant que nous avons configuré notre environnement, créons un playbook Ansible simple qui exécute notre script et capture sa sortie.

Création d'un playbook de base

Dans Ansible, les playbooks sont des fichiers YAML qui définissent un ensemble de tâches à exécuter sur des hôtes distants. Créons un playbook qui exécute notre script info.sh et capture sa sortie en utilisant le mot-clé register.

Créez un nouveau fichier nommé capture_output.yml dans le répertoire ~/project/ansible-output-demo :

  1. Cliquez sur le menu "File"
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom capture_output.yml dans le répertoire ~/project/ansible-output-demo

Ajoutez le contenu suivant au fichier capture_output.yml :

---
- name: Capture Script Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute the info.sh script
      command: "{{ playbook_dir }}/scripts/info.sh"
      register: script_output

    - name: Display the script output
      debug:
        var: script_output.stdout

Examinons ce playbook :

  1. Le playbook cible le groupe local défini dans notre inventaire.
  2. La première tâche exécute notre script info.sh en utilisant le module command.
  3. Le mot-clé register stocke la sortie de la commande dans une variable nommée script_output.
  4. La deuxième tâche utilise le module debug pour afficher la sortie standard (stdout) du script.

Exécution du playbook

Exécutons maintenant le playbook pour voir comment il capture et affiche la sortie du script :

cd ~/project/ansible-output-demo
ansible-playbook -i inventory capture_output.yml

Vous devriez voir une sortie similaire à la suivante :

PLAY [Capture Script Output] *******************************************

TASK [Execute the info.sh script] **************************************
changed: [localhost]

TASK [Display the script output] ***************************************
ok: [localhost] => {
    "script_output.stdout": "=== System Information ===\nHostname: ubuntu\nDate: Tue Oct 17 12:34:56 UTC 2023\nKernel: 5.15.0-1031-aws\nMemory:\n              total        used        free      shared  buff/cache   available\nMem:          7.7Gi       1.2Gi       5.2Gi        12Mi       1.3Gi       6.3Gi\nSwap:            0B          0B          0B\n=== Standard Output ===\nThis is standard output\nHello from the script!"
}

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

Notez que seule la sortie standard est affichée. La sortie d'erreur standard (stderr) n'est pas affichée car nous avons seulement demandé à afficher script_output.stdout.

Améliorer la lisibilité de la sortie

La sortie est un peu difficile à lire en tant que chaîne unique. Modifions notre playbook pour afficher la sortie dans un format plus lisible en utilisant l'attribut stdout_lines, qui présente la sortie sous forme de liste de lignes.

Modifiez le fichier capture_output.yml et modifiez la deuxième tâche comme suit :

- name: Display the script output
  debug:
    var: script_output.stdout_lines

Exécutez à nouveau le playbook :

ansible-playbook -i inventory capture_output.yml

Maintenant, la sortie devrait être plus lisible, chaque ligne étant affichée séparément :

TASK [Display the script output] ***************************************
ok: [localhost] => {
    "script_output.stdout_lines": [
        "=== System Information ===",
        "Hostname: ubuntu",
        "Date: Tue Oct 17 12:34:56 UTC 2023",
        "Kernel: 5.15.0-1031-aws",
        "Memory:",
        "              total        used        free      shared  buff/cache   available",
        "Mem:          7.7Gi       1.2Gi       5.2Gi        12Mi       1.3Gi       6.3Gi",
        "Swap:            0B          0B          0B",
        "=== Standard Output ===",
        "This is standard output",
        "Hello from the script!"
    ]
}

Ce format rend la sortie beaucoup plus facile à lire et à utiliser. Dans l'étape suivante, nous allons explorer comment capturer et afficher différents types de sortie.

Capture de différents types de sortie

Dans l'étape précédente, nous avons capturé et affiché la sortie standard de notre script. Cependant, lors de l'exécution de scripts, il existe plusieurs types de sortie que nous pourrions vouloir capturer :

  1. Sortie standard (stdout) : La sortie normale du script
  2. Erreur standard (stderr) : Messages d'erreur et avertissements
  3. Code de retour (rc) : L'état de sortie du script (0 signifie généralement succès, les valeurs non nulles indiquent des erreurs)

Créons un nouveau playbook qui capture et affiche les trois types de sortie.

Créez un nouveau fichier nommé capture_all_output.yml dans le répertoire ~/project/ansible-output-demo :

  1. Cliquez sur le menu "File"
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom capture_all_output.yml dans le répertoire ~/project/ansible-output-demo

Ajoutez le contenu suivant au fichier capture_all_output.yml :

---
- name: Capture All Types of Script Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute the info.sh script
      command: "{{ playbook_dir }}/scripts/info.sh"
      register: script_output

    - name: Display standard output
      debug:
        msg: "Standard Output (stdout):"

    - name: Display stdout content
      debug:
        var: script_output.stdout_lines

    - name: Display standard error
      debug:
        msg: "Standard Error (stderr):"

    - name: Display stderr content
      debug:
        var: script_output.stderr_lines

    - name: Display return code
      debug:
        msg: "Return Code: {{ script_output.rc }}"

Ce playbook exécute notre script, puis affiche :

  1. La sortie standard en utilisant script_output.stdout_lines
  2. L'erreur standard en utilisant script_output.stderr_lines
  3. Le code de retour en utilisant script_output.rc

Exécution du playbook amélioré

Exécutons notre nouveau playbook :

cd ~/project/ansible-output-demo
ansible-playbook -i inventory capture_all_output.yml

Vous devriez voir un affichage complet des trois types de sortie :

PLAY [Capture All Types of Script Output] *****************************

TASK [Execute the info.sh script] *************************************
changed: [localhost]

TASK [Display standard output] ****************************************
ok: [localhost] => {
    "msg": "Standard Output (stdout):"
}

TASK [Display stdout content] *****************************************
ok: [localhost] => {
    "script_output.stdout_lines": [
        "=== System Information ===",
        "Hostname: ubuntu",
        "Date: Tue Oct 17 12:40:22 UTC 2023",
        "Kernel: 5.15.0-1031-aws",
        "Memory:",
        "              total        used        free      shared  buff/cache   available",
        "Mem:          7.7Gi       1.2Gi       5.2Gi        12Mi       1.3Gi       6.3Gi",
        "Swap:            0B          0B          0B",
        "=== Standard Output ===",
        "This is standard output",
        "Hello from the script!"
    ]
}

TASK [Display standard error] *****************************************
ok: [localhost] => {
    "msg": "Standard Error (stderr):"
}

TASK [Display stderr content] *****************************************
ok: [localhost] => {
    "script_output.stderr_lines": [
        "=== Standard Error ===",
        "This is standard error",
        "An example error message"
    ]
}

TASK [Display return code] ********************************************
ok: [localhost] => {
    "msg": "Return Code: 0"
}

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

Maintenant, nous pouvons voir tous les types de sortie de notre script :

  • La sortie standard affiche les informations système et nos messages réguliers
  • L'erreur standard affiche nos messages d'erreur
  • Le code de retour est 0, indiquant une exécution réussie

Création d'un script avec des erreurs

Créons un script qui produira une erreur et renverra un code de sortie non nul pour voir comment Ansible le gère.

Créez un nouveau fichier nommé error.sh dans le répertoire scripts :

  1. Cliquez sur le menu "File"
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom scripts/error.sh dans le répertoire ~/project/ansible-output-demo

Ajoutez le contenu suivant au fichier error.sh :

#!/bin/bash

## Print some standard output
echo "Starting error demonstration script"
echo "This will appear in stdout"

## Print some standard error
echo "This will appear in stderr" >&2
echo "Error: Something went wrong!" >&2

## Exit with a non-zero code to indicate error
exit 1

Rendez le script exécutable :

chmod +x ~/project/ansible-output-demo/scripts/error.sh

Maintenant, créons un playbook pour exécuter ce script et gérer l'erreur. Créez un nouveau fichier nommé handle_errors.yml :

  1. Cliquez sur le menu "File"
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom handle_errors.yml dans le répertoire ~/project/ansible-output-demo

Ajoutez le contenu suivant au fichier handle_errors.yml :

---
- name: Handle Script Errors
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute the error script
      command: "{{ playbook_dir }}/scripts/error.sh"
      register: script_output
      ignore_errors: yes

    - name: Display standard output
      debug:
        var: script_output.stdout_lines

    - name: Display standard error
      debug:
        var: script_output.stderr_lines

    - name: Display return code
      debug:
        msg: "Return Code: {{ script_output.rc }}"

    - name: Check if script failed
      debug:
        msg: "The script failed with return code {{ script_output.rc }}"
      when: script_output.rc != 0

Notez l'ajout de ignore_errors: yes qui indique à Ansible de continuer à exécuter le playbook même si la commande échoue (renvoie un code de sortie non nul).

Exécutons ce playbook :

ansible-playbook -i inventory handle_errors.yml

Vous devriez voir une sortie similaire à la suivante :

PLAY [Handle Script Errors] *******************************************

TASK [Execute the error script] ***************************************
changed: [localhost]

TASK [Display standard output] ****************************************
ok: [localhost] => {
    "script_output.stdout_lines": [
        "Starting error demonstration script",
        "This will appear in stdout"
    ]
}

TASK [Display standard error] *****************************************
ok: [localhost] => {
    "script_output.stderr_lines": [
        "This will appear in stderr",
        "Error: Something went wrong!"
    ]
}

TASK [Display return code] ********************************************
ok: [localhost] => {
    "msg": "Return Code: 1"
}

TASK [Check if script failed] *****************************************
ok: [localhost] => {
    "msg": "The script failed with return code 1"
}

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

Cet exemple démontre comment :

  1. Capturer la sortie d'un script qui produit une erreur
  2. Continuer l'exécution du playbook malgré l'erreur
  3. Exécuter conditionnellement des tâches en fonction du code de retour du script

Dans l'étape suivante, nous allons explorer des cas d'utilisation plus avancés et les meilleures pratiques pour travailler avec la sortie de script dans Ansible.

Traitement avancé de la sortie et cas d'utilisation pratiques

Maintenant que nous comprenons comment capturer différents types de sortie, explorons des techniques plus avancées pour traiter et utiliser la sortie de script dans Ansible.

Analyse de la sortie avec des filtres

Ansible fournit divers filtres qui vous permettent de manipuler et d'extraire des informations spécifiques de la sortie de script. Dans cette section, nous examinerons quelques techniques de filtrage courantes.

Créez un nouveau fichier nommé parse_output.yml dans le répertoire ~/project/ansible-output-demo :

  1. Cliquez sur le menu "File"
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom parse_output.yml dans le répertoire ~/project/ansible-output-demo

Tout d'abord, créons un script qui génère une sortie structurée que nous pourrons analyser. Créez un nouveau fichier nommé system_stats.sh :

  1. Cliquez sur le menu "File"
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom scripts/system_stats.sh dans le répertoire ~/project/ansible-output-demo

Ajoutez le contenu suivant au fichier system_stats.sh :

#!/bin/bash

## Display CPU info
echo "CPU_MODEL: $(grep 'model name' /proc/cpuinfo | head -1 | cut -d ':' -f2 | xargs)"
echo "CPU_CORES: $(grep -c 'processor' /proc/cpuinfo)"

## Display memory info in GB
mem_total=$(free -g | grep Mem | awk '{print $2}')
echo "MEMORY_GB: $mem_total"

## Display disk usage
disk_usage=$(df -h / | tail -1 | awk '{print $5}' | tr -d '%')
echo "DISK_USAGE_PCT: $disk_usage"

## Display load average
load_avg=$(uptime | awk -F'load average: ' '{print $2}' | cut -d, -f1)
echo "LOAD_AVG: $load_avg"

exit 0

Rendez le script exécutable :

chmod +x ~/project/ansible-output-demo/scripts/system_stats.sh

Maintenant, créons un playbook qui exécute ce script, capture sa sortie et l'analyse pour extraire des informations spécifiques :

Ajoutez le contenu suivant au fichier parse_output.yml :

---
- name: Parse Script Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute the system_stats.sh script
      command: "{{ playbook_dir }}/scripts/system_stats.sh"
      register: stats_output

    - name: Display raw output
      debug:
        var: stats_output.stdout_lines

    - name: Parse CPU model
      set_fact:
        cpu_model: "{{ stats_output.stdout | regex_search('CPU_MODEL: (.+)', '\\1') | first }}"

    - name: Parse CPU cores
      set_fact:
        cpu_cores: "{{ stats_output.stdout | regex_search('CPU_CORES: (\\d+)', '\\1') | first }}"

    - name: Parse memory
      set_fact:
        memory_gb: "{{ stats_output.stdout | regex_search('MEMORY_GB: (\\d+)', '\\1') | first }}"

    - name: Parse disk usage
      set_fact:
        disk_usage: "{{ stats_output.stdout | regex_search('DISK_USAGE_PCT: (\\d+)', '\\1') | first }}"

    - name: Parse load average
      set_fact:
        load_avg: "{{ stats_output.stdout | regex_search('LOAD_AVG: ([0-9.]+)', '\\1') | first }}"

    - name: Display parsed information
      debug:
        msg: |
          Parsed system information:
          - CPU Model: {{ cpu_model }}
          - CPU Cores: {{ cpu_cores }}
          - Memory (GB): {{ memory_gb }}
          - Disk Usage (%): {{ disk_usage }}
          - Load Average: {{ load_avg }}

Ce playbook :

  1. Exécute notre script system_stats.sh
  2. Affiche la sortie brute
  3. Utilise le filtre regex_search pour extraire des informations spécifiques de la sortie
  4. Stocke les informations extraites dans des variables
  5. Affiche les informations analysées dans un format structuré

Exécutons ce playbook :

cd ~/project/ansible-output-demo
ansible-playbook -i inventory parse_output.yml

Vous devriez voir une sortie similaire à la suivante :

PLAY [Parse Script Output] ********************************************

TASK [Execute the system_stats.sh script] *****************************
changed: [localhost]

TASK [Display raw output] *********************************************
ok: [localhost] => {
    "stats_output.stdout_lines": [
        "CPU_MODEL: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz",
        "CPU_CORES: 2",
        "MEMORY_GB: 7",
        "DISK_USAGE_PCT: 58",
        "LOAD_AVG: 0.08"
    ]
}

TASK [Parse CPU model] ************************************************
ok: [localhost]

TASK [Parse CPU cores] ************************************************
ok: [localhost]

TASK [Parse memory] ***************************************************
ok: [localhost]

TASK [Parse disk usage] ***********************************************
ok: [localhost]

TASK [Parse load average] *********************************************
ok: [localhost]

TASK [Display parsed information] *************************************
ok: [localhost] => {
    "msg": "Parsed system information:\n- CPU Model: Intel(R) Xeon(R) CPU E5-2676 v3 @ 2.40GHz\n- CPU Cores: 2\n- Memory (GB): 7\n- Disk Usage (%): 58\n- Load Average: 0.08"
}

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

Prendre des décisions basées sur la sortie

L'un des aspects les plus puissants de la capture de la sortie de script est de l'utiliser pour prendre des décisions dans vos playbooks Ansible. Créons un playbook qui démontre l'exécution conditionnelle basée sur la sortie de script.

Créez un nouveau fichier nommé conditional_actions.yml dans le répertoire ~/project/ansible-output-demo :

  1. Cliquez sur le menu "File"
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom conditional_actions.yml dans le répertoire ~/project/ansible-output-demo

Ajoutez le contenu suivant :

---
- name: Conditional Actions Based on Script Output
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute the system_stats.sh script
      command: "{{ playbook_dir }}/scripts/system_stats.sh"
      register: stats_output

    - name: Parse disk usage
      set_fact:
        disk_usage: "{{ stats_output.stdout | regex_search('DISK_USAGE_PCT: (\\d+)', '\\1') | first | int }}"

    - name: Parse load average
      set_fact:
        load_avg: "{{ stats_output.stdout | regex_search('LOAD_AVG: ([0-9.]+)', '\\1') | first | float }}"

    - name: Display system status
      debug:
        msg: "Current system status: Disk usage: {{ disk_usage }}%, Load average: {{ load_avg }}"

    - name: Warn about high disk usage
      debug:
        msg: "WARNING: Disk usage is high at {{ disk_usage }}%. Consider cleaning up disk space."
      when: disk_usage > 50

    - name: Warn about high load average
      debug:
        msg: "WARNING: Load average is high at {{ load_avg }}. Check for resource-intensive processes."
      when: load_avg > 1.0

    - name: Report healthy system
      debug:
        msg: "System is healthy. All metrics within normal ranges."
      when: disk_usage <= 50 and load_avg <= 1.0

Ce playbook :

  1. Exécute le script system_stats.sh
  2. Analyse les valeurs d'utilisation du disque et de la charge moyenne
  3. Affiche différents messages en fonction des valeurs :
    • Un avertissement si l'utilisation du disque est supérieure à 50 %
    • Un avertissement si la charge moyenne est supérieure à 1,0
    • Un message "système sain" si toutes les métriques sont dans les plages normales

Exécutons ce playbook :

ansible-playbook -i inventory conditional_actions.yml

La sortie dépendra de l'état actuel de votre système, mais elle devrait inclure des messages conditionnels basés sur votre utilisation du disque et votre charge moyenne.

Ces exemples démontrent comment vous pouvez :

  1. Analyser et extraire des informations spécifiques de la sortie de script
  2. Utiliser ces informations pour prendre des décisions dans vos playbooks Ansible
  3. Prendre différentes mesures en fonction de la sortie du script

Ces techniques sont essentielles pour créer des flux de travail d'automatisation dynamiques et réactifs qui peuvent s'adapter à différentes conditions et scénarios.

Cas d'utilisation réel - Vérification de l'état du système

Dans cette dernière étape, nous allons créer un exemple complet du monde réel qui rassemble tout ce que nous avons appris sur la capture et le traitement de la sortie de script avec Ansible. Nous allons construire un outil de vérification de l'état du système qui :

  1. Collecte diverses métriques système
  2. Analyse les métriques pour identifier les problèmes potentiels
  3. Génère un rapport d'état
  4. Prend des mesures correctives si nécessaire

Création du script de vérification de l'état

Tout d'abord, créons un script complet de vérification de l'état qui collecte diverses métriques système.

Créez un nouveau fichier nommé health_check.sh dans le répertoire scripts :

  1. Cliquez sur le menu "File"
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom scripts/health_check.sh dans le répertoire ~/project/ansible-output-demo

Ajoutez le contenu suivant au fichier health_check.sh :

#!/bin/bash

## System Health Check Script

echo "HEALTH_CHECK_START: $(date)"

## CPU load
cpu_load=$(uptime | awk -F'load average: ' '{print $2}' | cut -d, -f1)
echo "CPU_LOAD: $cpu_load"
if (($(echo "$cpu_load > 1.0" | bc -l))); then
  echo "CPU_STATUS: WARNING"
else
  echo "CPU_STATUS: OK"
fi

## Memory usage
mem_total=$(free | grep Mem | awk '{print $2}')
mem_used=$(free | grep Mem | awk '{print $3}')
mem_pct=$(echo "scale=2; $mem_used / $mem_total * 100" | bc)
echo "MEM_USAGE_PCT: $mem_pct"
if (($(echo "$mem_pct > 80" | bc -l))); then
  echo "MEM_STATUS: WARNING"
else
  echo "MEM_STATUS: OK"
fi

## Disk usage
disk_usage=$(df -h / | tail -1 | awk '{print $5}' | tr -d '%')
echo "DISK_USAGE_PCT: $disk_usage"
if [ "$disk_usage" -gt 80 ]; then
  echo "DISK_STATUS: WARNING"
else
  echo "DISK_STATUS: OK"
fi

## Check for zombie processes
zombie_count=$(ps aux | grep -c Z)
echo "ZOMBIE_PROCESSES: $zombie_count"
if [ "$zombie_count" -gt 0 ]; then
  echo "ZOMBIE_STATUS: WARNING"
else
  echo "ZOMBIE_STATUS: OK"
fi

## Check system uptime
uptime_days=$(uptime | awk '{print $3}')
echo "UPTIME_DAYS: $uptime_days"

## Check last 5 log entries for errors
echo "RECENT_ERRORS: $(grep -i error /var/log/syslog 2> /dev/null | tail -5 | wc -l)"

echo "HEALTH_CHECK_END: $(date)"

Rendez le script exécutable :

chmod +x ~/project/ansible-output-demo/scripts/health_check.sh

Création du playbook de vérification de l'état

Maintenant, créons un playbook complet qui exécute le script de vérification de l'état, analyse les résultats et prend les mesures appropriées en fonction des résultats.

Créez un nouveau fichier nommé system_health_check.yml dans le répertoire ~/project/ansible-output-demo :

  1. Cliquez sur le menu "File"
  2. Sélectionnez "New File"
  3. Enregistrez-le sous le nom system_health_check.yml dans le répertoire ~/project/ansible-output-demo

Ajoutez le contenu suivant au fichier system_health_check.yml :

---
- name: System Health Check
  hosts: local
  gather_facts: no

  tasks:
    - name: Execute health check script
      command: "{{ playbook_dir }}/scripts/health_check.sh"
      register: health_check

    - name: Display raw health check output
      debug:
        var: health_check.stdout_lines

    ## Parse metrics from the health check output
    - name: Parse CPU load
      set_fact:
        cpu_load: "{{ health_check.stdout | regex_search('CPU_LOAD: ([0-9.]+)', '\\1') | first | float }}"
        cpu_status: "{{ health_check.stdout | regex_search('CPU_STATUS: (\\w+)', '\\1') | first }}"

    - name: Parse memory usage
      set_fact:
        mem_usage: "{{ health_check.stdout | regex_search('MEM_USAGE_PCT: ([0-9.]+)', '\\1') | first | float }}"
        mem_status: "{{ health_check.stdout | regex_search('MEM_STATUS: (\\w+)', '\\1') | first }}"

    - name: Parse disk usage
      set_fact:
        disk_usage: "{{ health_check.stdout | regex_search('DISK_USAGE_PCT: (\\d+)', '\\1') | first | int }}"
        disk_status: "{{ health_check.stdout | regex_search('DISK_STATUS: (\\w+)', '\\1') | first }}"

    - name: Parse zombie processes
      set_fact:
        zombie_count: "{{ health_check.stdout | regex_search('ZOMBIE_PROCESSES: (\\d+)', '\\1') | first | int }}"
        zombie_status: "{{ health_check.stdout | regex_search('ZOMBIE_STATUS: (\\w+)', '\\1') | first }}"

    ## Generate a health status summary
    - name: Generate health status summary
      set_fact:
        health_status:
          cpu:
            load: "{{ cpu_load }}"
            status: "{{ cpu_status }}"
          memory:
            usage_percent: "{{ mem_usage }}"
            status: "{{ mem_status }}"
          disk:
            usage_percent: "{{ disk_usage }}"
            status: "{{ disk_status }}"
          processes:
            zombie_count: "{{ zombie_count }}"
            status: "{{ zombie_status }}"

    ## Display health summary
    - name: Display health summary
      debug:
        var: health_status

    ## Check overall system status
    - name: Determine overall system status
      set_fact:
        overall_status: "{{ 'WARNING' if (cpu_status == 'WARNING' or mem_status == 'WARNING' or disk_status == 'WARNING' or zombie_status == 'WARNING') else 'OK' }}"

    - name: Display overall system status
      debug:
        msg: "Overall System Status: {{ overall_status }}"

    ## Take remedial actions if necessary
    - name: Recommend actions for CPU issues
      debug:
        msg: "Action recommended: Check for resource-intensive processes using 'top' or 'htop'"
      when: cpu_status == "WARNING"

    - name: Recommend actions for memory issues
      debug:
        msg: "Action recommended: Free up memory by restarting services or clearing cache"
      when: mem_status == "WARNING"

    - name: Recommend actions for disk issues
      debug:
        msg: "Action recommended: Clean up disk space using 'du -sh /* | sort -hr' to identify large directories"
      when: disk_status == "WARNING"

    - name: Recommend actions for zombie processes
      debug:
        msg: "Action recommended: Identify and restart parent processes of zombies"
      when: zombie_status == "WARNING"

    ## Generate health report file
    - name: Create health report directory
      file:
        path: "{{ playbook_dir }}/reports"
        state: directory

    - name: Get current timestamp
      command: date "+%Y%m%d_%H%M%S"
      register: timestamp

    - name: Create health report file
      copy:
        content: |
          System Health Report - {{ timestamp.stdout }}
          ----------------------------------------------

          CPU:
            Load Average: {{ cpu_load }}
            Status: {{ cpu_status }}

          Memory:
            Usage: {{ mem_usage }}%
            Status: {{ mem_status }}

          Disk:
            Usage: {{ disk_usage }}%
            Status: {{ disk_status }}

          Processes:
            Zombie Count: {{ zombie_count }}
            Status: {{ zombie_status }}

          Overall Status: {{ overall_status }}

          Recommendations:
          {% if cpu_status == "WARNING" %}
          - CPU: Check for resource-intensive processes using 'top' or 'htop'
          {% endif %}
          {% if mem_status == "WARNING" %}
          - Memory: Free up memory by restarting services or clearing cache
          {% endif %}
          {% if disk_status == "WARNING" %}
          - Disk: Clean up disk space using 'du -sh /* | sort -hr' to identify large directories
          {% endif %}
          {% if zombie_status == "WARNING" %}
          - Processes: Identify and restart parent processes of zombies
          {% endif %}
          {% if overall_status == "OK" %}
          - System is healthy. No actions required.
          {% endif %}
        dest: "{{ playbook_dir }}/reports/health_report_{{ timestamp.stdout }}.txt"

    - name: Display report location
      debug:
        msg: "Health report saved to {{ playbook_dir }}/reports/health_report_{{ timestamp.stdout }}.txt"

Ce playbook complet :

  1. Exécute notre script de vérification de l'état
  2. Analyse les différentes métriques de la sortie du script
  3. Crée un résumé structuré de l'état du système
  4. Détermine l'état général du système en fonction de l'état des composants individuels
  5. Fournit des recommandations spécifiques pour tout problème détecté
  6. Génère un fichier de rapport d'état détaillé avec un horodatage

Exécution de la vérification de l'état

Exécutons notre playbook de vérification de l'état du système :

cd ~/project/ansible-output-demo
ansible-playbook -i inventory system_health_check.yml

Vous devriez voir une sortie détaillée montrant l'état du système, ainsi que toutes les recommandations nécessaires pour l'améliorer. La sortie variera en fonction de l'état actuel de votre système.

Après avoir exécuté le playbook, vérifiez le répertoire des rapports pour voir le rapport d'état généré :

ls -l ~/project/ansible-output-demo/reports/

Vous devriez voir un fichier nommé health_report_[timestamp].txt. Affichez le contenu de ce fichier :

cat ~/project/ansible-output-demo/reports/health_report_*.txt

Résumé de ce que nous avons appris

Tout au long de ce tutoriel, nous avons appris :

  1. Comment capturer différents types de sortie (stdout, stderr, codes de retour) à partir de scripts exécutés par Ansible
  2. Comment analyser et extraire des informations spécifiques de la sortie de script à l'aide des filtres Ansible
  3. Comment utiliser la sortie de script pour prendre des décisions et effectuer des actions conditionnelles
  4. Comment implémenter une solution complète du monde réel qui exploite la sortie de script pour la surveillance de l'état du système

Ces techniques sont des outils puissants dans votre boîte à outils d'automatisation Ansible, vous permettant de créer des flux de travail d'automatisation sophistiqués, dynamiques et réactifs.

Résumé

Dans ce laboratoire, nous avons exploré comment capturer et utiliser efficacement la sortie de scripts exécutés via Ansible. Nous avons commencé par la capture de sortie de base en utilisant le mot-clé register et sommes passés à des techniques plus avancées telles que l'analyse de la sortie avec des filtres et la prise de décisions basées sur les résultats des scripts.

Les principaux points à retenir de ce tutoriel sont les suivants :

  1. La capacité de capturer différents types de sortie (stdout, stderr, codes de retour) à partir de scripts exécutés par Ansible
  2. Des techniques pour analyser et extraire des informations spécifiques de la sortie de script
  3. Des méthodes pour exécuter conditionnellement des tâches en fonction de la sortie du script
  4. Un exemple complet du monde réel démontrant comment construire une solution de surveillance de l'état du système avec Ansible

En maîtrisant ces techniques, vous pouvez créer des flux de travail d'automatisation plus sophistiqués, dynamiques et réactifs qui peuvent s'adapter à différentes conditions et scénarios. Cette capacité est essentielle pour une gestion efficace de l'infrastructure, le déploiement d'applications et l'administration système à l'aide d'Ansible.

Au fur et à mesure que vous poursuivez votre parcours avec Ansible, rappelez-vous que la capture de la sortie de script n'est qu'une des nombreuses fonctionnalités puissantes qu'Ansible offre. L'exploration d'autres capacités d'Ansible telles que les rôles, les modèles et le coffre-fort améliorera encore votre boîte à outils d'automatisation.