Como Capturar a Saída de um Script Executado pelo Ansible

AnsibleBeginner
Pratique Agora

Introdução

Ansible é uma ferramenta de automação de TI amplamente utilizada que simplifica o gerenciamento de infraestruturas complexas e implantações de aplicações. Neste tutorial, exploraremos como capturar a saída de scripts executados através de playbooks do Ansible. Essa capacidade é essencial para monitorar, depurar e analisar os resultados de suas tarefas de automação. Ao final deste laboratório, você entenderá várias técnicas para capturar e utilizar a saída de scripts em seus fluxos de trabalho do Ansible.

Configurando o Ambiente Ansible

Antes de começarmos a capturar saídas de scripts com Ansible, precisamos configurar um ambiente Ansible básico. Isso inclui a criação da estrutura de diretórios e arquivos de configuração necessários.

Entendendo os Fundamentos do Ansible

O Ansible funciona conectando-se aos hosts de destino e enviando pequenos programas chamados módulos. Esses módulos são executados nos hosts de destino e removidos quando concluídos. O Ansible é agent-less (sem agente), o que significa que você não precisa instalar nenhum software especial nos nós gerenciados.

Vamos começar criando um diretório de projeto e os arquivos Ansible necessários:

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

Agora, vamos criar um arquivo de inventário simples. No Ansible, o arquivo de inventário define os hosts e grupos de hosts nos quais comandos, módulos e tarefas em um playbook operam.

Crie um arquivo de inventário usando o editor de código:

  1. Clique no menu "File" (Arquivo) no canto superior esquerdo da IDE
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como inventory no diretório ~/project/ansible-output-demo

Adicione o seguinte conteúdo ao arquivo inventory:

[local]
localhost ansible_connection=local

Este arquivo de inventário especifica que executaremos o Ansible na máquina local.

Em seguida, vamos criar um script simples que gerará alguma saída para capturarmos. Este script irá:

  1. Imprimir algumas informações do sistema
  2. Gerar alguma saída padrão
  3. Gerar alguma saída de erro padrão

Crie um novo arquivo no diretório scripts chamado info.sh:

  1. Clique no menu "File" (Arquivo)
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como scripts/info.sh no diretório ~/project/ansible-output-demo

Adicione o seguinte conteúdo ao arquivo 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

Agora, vamos tornar o script executável:

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

Vamos executar o script diretamente para ver qual saída ele produz:

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

Você deve ver uma saída contendo informações do sistema, mensagens de saída padrão e mensagens de erro padrão.

Agora temos nosso ambiente básico configurado. No próximo passo, criaremos um playbook do Ansible para executar este script e capturar sua saída.

Captura Básica de Saída com Ansible

Agora que configuramos nosso ambiente, vamos criar um playbook Ansible simples que executa nosso script e captura sua saída.

Criando um Playbook Básico

No Ansible, playbooks são arquivos YAML que definem um conjunto de tarefas a serem executadas em hosts remotos. Vamos criar um playbook que executa nosso script info.sh e captura sua saída usando a palavra-chave register.

Crie um novo arquivo chamado capture_output.yml no diretório ~/project/ansible-output-demo:

  1. Clique no menu "File" (Arquivo)
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como capture_output.yml no diretório ~/project/ansible-output-demo

Adicione o seguinte conteúdo ao arquivo 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

Vamos examinar este playbook:

  1. O playbook tem como alvo o grupo local definido em nosso inventário.
  2. A primeira tarefa executa nosso script info.sh usando o módulo command.
  3. A palavra-chave register armazena a saída do comando em uma variável chamada script_output.
  4. A segunda tarefa usa o módulo debug para exibir a saída padrão (stdout) do script.

Executando o Playbook

Agora, vamos executar o playbook para ver como ele captura e exibe a saída do script:

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

Você deve ver uma saída semelhante à seguinte:

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

Observe que apenas a saída padrão é exibida. A saída de erro padrão (stderr) não é mostrada porque pedimos apenas para exibir script_output.stdout.

Melhorando a Legibilidade da Saída

A saída é um pouco difícil de ler como uma única string. Vamos modificar nosso playbook para exibir a saída em um formato mais legível usando o atributo stdout_lines, que apresenta a saída como uma lista de linhas.

Edite o arquivo capture_output.yml e modifique a segunda tarefa da seguinte forma:

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

Execute o playbook novamente:

ansible-playbook -i inventory capture_output.yml

Agora a saída deve ser mais legível, com cada linha exibida separadamente:

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!"
    ]
}

Este formato torna a saída muito mais fácil de ler e trabalhar. No próximo passo, exploraremos como capturar e exibir diferentes tipos de saída.

Capturando Diferentes Tipos de Saída

No passo anterior, capturamos e exibimos a saída padrão do nosso script. No entanto, ao executar scripts, existem vários tipos de saída que podemos querer capturar:

  1. Saída Padrão (stdout): A saída normal do script
  2. Erro Padrão (stderr): Mensagens de erro e avisos
  3. Código de Retorno (rc): O status de saída do script (0 normalmente significa sucesso, valores diferentes de zero indicam erros)

Vamos criar um novo playbook que captura e exibe todos os três tipos de saída.

Crie um novo arquivo chamado capture_all_output.yml no diretório ~/project/ansible-output-demo:

  1. Clique no menu "File" (Arquivo)
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como capture_all_output.yml no diretório ~/project/ansible-output-demo

Adicione o seguinte conteúdo ao arquivo 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 }}"

Este playbook executa nosso script e, em seguida, exibe:

  1. A saída padrão usando script_output.stdout_lines
  2. O erro padrão usando script_output.stderr_lines
  3. O código de retorno usando script_output.rc

Executando o Playbook Aprimorado

Vamos executar nosso novo playbook:

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

Você deve ver uma exibição abrangente de todos os três tipos de saída:

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

Agora podemos ver todos os tipos de saída do nosso script:

  • A saída padrão mostra informações do sistema e nossas mensagens regulares
  • O erro padrão mostra nossas mensagens de erro
  • O código de retorno é 0, indicando execução bem-sucedida

Criando um Script com Erros

Vamos criar um script que produzirá um erro e retornará um código de saída diferente de zero para ver como o Ansible o trata.

Crie um novo arquivo chamado error.sh no diretório scripts:

  1. Clique no menu "File" (Arquivo)
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como scripts/error.sh no diretório ~/project/ansible-output-demo

Adicione o seguinte conteúdo ao arquivo 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

Torne o script executável:

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

Agora, vamos criar um playbook para executar este script e lidar com o erro. Crie um novo arquivo chamado handle_errors.yml:

  1. Clique no menu "File" (Arquivo)
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como handle_errors.yml no diretório ~/project/ansible-output-demo

Adicione o seguinte conteúdo ao arquivo 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

Observe a adição de ignore_errors: yes, que informa ao Ansible para continuar executando o playbook mesmo que o comando falhe (retorne um código de saída diferente de zero).

Vamos executar este playbook:

ansible-playbook -i inventory handle_errors.yml

Você deve ver uma saída semelhante à seguinte:

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

Este exemplo demonstra como:

  1. Capturar a saída de um script que produz um erro
  2. Continuar a execução do playbook apesar do erro
  3. Executar condicionalmente tarefas com base no código de retorno do script

No próximo passo, exploraremos casos de uso mais avançados e as melhores práticas para trabalhar com a saída de scripts no Ansible.

Processamento Avançado de Saída e Casos de Uso Práticos

Agora que entendemos como capturar diferentes tipos de saída, vamos explorar algumas técnicas mais avançadas para processar e utilizar a saída de scripts no Ansible.

Análise da Saída com Filtros

O Ansible fornece vários filtros que permitem manipular e extrair informações específicas da saída do script. Nesta seção, veremos algumas técnicas comuns de filtragem.

Crie um novo arquivo chamado parse_output.yml no diretório ~/project/ansible-output-demo:

  1. Clique no menu "File" (Arquivo)
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como parse_output.yml no diretório ~/project/ansible-output-demo

Primeiro, vamos criar um script que gera alguma saída estruturada que podemos analisar. Crie um novo arquivo chamado system_stats.sh:

  1. Clique no menu "File" (Arquivo)
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como scripts/system_stats.sh no diretório ~/project/ansible-output-demo

Adicione o seguinte conteúdo ao arquivo 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

Torne o script executável:

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

Agora, vamos criar um playbook que executa este script, captura sua saída e a analisa para extrair informações específicas:

Adicione o seguinte conteúdo ao arquivo 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 }}

Este playbook:

  1. Executa nosso script system_stats.sh
  2. Exibe a saída bruta
  3. Usa o filtro regex_search para extrair informações específicas da saída
  4. Armazena as informações extraídas em variáveis
  5. Exibe as informações analisadas em um formato estruturado

Vamos executar este playbook:

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

Você deve ver uma saída semelhante à seguinte:

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

Tomando Decisões com Base na Saída

Um dos aspectos mais poderosos da captura da saída do script é usá-la para tomar decisões em seus playbooks Ansible. Vamos criar um playbook que demonstra a execução condicional com base na saída do script.

Crie um novo arquivo chamado conditional_actions.yml no diretório ~/project/ansible-output-demo:

  1. Clique no menu "File" (Arquivo)
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como conditional_actions.yml no diretório ~/project/ansible-output-demo

Adicione o seguinte conteúdo:

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

Este playbook:

  1. Executa o script system_stats.sh
  2. Analisa os valores de uso do disco e média de carga
  3. Exibe mensagens diferentes com base nos valores:
    • Um aviso se o uso do disco for superior a 50%
    • Um aviso se a média de carga for superior a 1,0
    • Uma mensagem de "sistema saudável" se todas as métricas estiverem dentro das faixas normais

Vamos executar este playbook:

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

A saída dependerá do estado atual do seu sistema, mas deve incluir mensagens condicionais com base no uso do disco e na média de carga.

Estes exemplos demonstram como você pode:

  1. Analisar e extrair informações específicas da saída do script
  2. Usar essas informações para tomar decisões em seus playbooks Ansible
  3. Tomar diferentes ações com base na saída do script

Essas técnicas são essenciais para criar fluxos de trabalho de automação dinâmicos e responsivos que podem se adaptar a diferentes condições e cenários.

Caso de Uso do Mundo Real - Verificação de Integridade do Sistema

Neste passo final, criaremos um exemplo completo do mundo real que reúne tudo o que aprendemos sobre a captura e o processamento da saída do script com o Ansible. Construiremos uma ferramenta de verificação de integridade do sistema que:

  1. Coleta várias métricas do sistema
  2. Analisa as métricas para identificar possíveis problemas
  3. Gera um relatório de integridade
  4. Toma medidas corretivas quando necessário

Criando o Script de Verificação de Integridade

Primeiro, vamos criar um script abrangente de verificação de integridade que coleta várias métricas do sistema.

Crie um novo arquivo chamado health_check.sh no diretório scripts:

  1. Clique no menu "File" (Arquivo)
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como scripts/health_check.sh no diretório ~/project/ansible-output-demo

Adicione o seguinte conteúdo ao arquivo 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)"

Torne o script executável:

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

Criando o Playbook de Verificação de Integridade

Agora, vamos criar um playbook abrangente que executa o script de verificação de integridade, analisa os resultados e toma as ações apropriadas com base nas descobertas.

Crie um novo arquivo chamado system_health_check.yml no diretório ~/project/ansible-output-demo:

  1. Clique no menu "File" (Arquivo)
  2. Selecione "New File" (Novo Arquivo)
  3. Salve-o como system_health_check.yml no diretório ~/project/ansible-output-demo

Adicione o seguinte conteúdo ao arquivo 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"

Este playbook abrangente:

  1. Executa nosso script de verificação de integridade
  2. Analisa as várias métricas da saída do script
  3. Cria um resumo estruturado da integridade do sistema
  4. Determina o status geral do sistema com base nos status dos componentes individuais
  5. Fornece recomendações específicas para quaisquer problemas detectados
  6. Gera um arquivo de relatório de integridade detalhado com carimbo de data/hora

Executando a Verificação de Integridade

Vamos executar nosso playbook de verificação de integridade do sistema:

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

Você deve ver uma saída detalhada mostrando o status de integridade do sistema, juntamente com quaisquer recomendações necessárias para melhoria. A saída variará dependendo do estado atual do seu sistema.

Após executar o playbook, verifique o diretório de relatórios para ver o relatório de integridade gerado:

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

Você deve ver um arquivo chamado health_report_[timestamp].txt. Visualize o conteúdo deste arquivo:

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

Resumo do Que Aprendemos

Ao longo deste tutorial, aprendemos:

  1. Como capturar diferentes tipos de saída (stdout, stderr, códigos de retorno) de scripts executados pelo Ansible
  2. Como analisar e extrair informações específicas da saída do script usando filtros Ansible
  3. Como usar a saída do script para tomar decisões e realizar ações condicionais
  4. Como implementar uma solução completa do mundo real que aproveita a saída do script para monitoramento da integridade do sistema

Essas técnicas são ferramentas poderosas em seu kit de ferramentas de automação Ansible, permitindo que você crie fluxos de trabalho de automação sofisticados, dinâmicos e responsivos.

Resumo

Neste laboratório, exploramos como capturar e utilizar efetivamente a saída de scripts executados através do Ansible. Começamos com a captura básica de saída usando a palavra-chave register e progredimos para técnicas mais avançadas, como a análise da saída com filtros e a tomada de decisões com base nos resultados do script.

Os principais pontos deste tutorial incluem:

  1. A capacidade de capturar diferentes tipos de saída (stdout, stderr, códigos de retorno) de scripts executados pelo Ansible
  2. Técnicas para analisar e extrair informações específicas da saída do script
  3. Métodos para executar tarefas condicionalmente com base na saída do script
  4. Um exemplo abrangente do mundo real demonstrando como construir uma solução de monitoramento da integridade do sistema com o Ansible

Ao dominar essas técnicas, você pode criar fluxos de trabalho de automação mais sofisticados, dinâmicos e responsivos que podem se adaptar a diferentes condições e cenários. Essa capacidade é essencial para o gerenciamento eficaz da infraestrutura, implantação de aplicativos e administração de sistemas usando o Ansible.

Ao continuar sua jornada no Ansible, lembre-se de que a captura da saída do script é apenas um dos muitos recursos poderosos que o Ansible oferece. Explorar outros recursos do Ansible, como roles (papéis), templates (modelos) e vault (cofre), aprimorará ainda mais seu kit de ferramentas de automação.