Introducción
Ansible es una poderosa herramienta de automatización que ayuda a los administradores de sistemas y desarrolladores a gestionar la infraestructura de manera eficiente. Al ejecutar scripts o comandos a través de playbooks de Ansible, a menudo es crucial capturar y mostrar su salida con fines de monitoreo y solución de problemas.
En este laboratorio práctico, aprenderá a mostrar eficazmente la salida de scripts en sus playbooks de Ansible. Comenzaremos con los conceptos básicos de la estructura de un playbook de Ansible, luego exploraremos varias técnicas para capturar y mostrar las salidas de los comandos, y finalmente cubriremos algunos métodos avanzados para formatear y filtrar los datos de salida.
Al final de este laboratorio, tendrá experiencia práctica con diferentes enfoques para manejar la salida de scripts en Ansible, lo que le permitirá crear flujos de trabajo de automatización más informativos y fáciles de depurar.
Configuración de su Primer Playbook de Ansible
Antes de que podamos explorar cómo mostrar la salida de scripts, necesitamos configurar un entorno básico de Ansible y crear nuestro primer playbook.
Instalación de Ansible
Comencemos asegurándonos de que Ansible esté instalado en nuestro sistema:
sudo apt update
sudo apt install -y ansible
Este comando instalará Ansible en su sistema Ubuntu. Una vez que la instalación esté completa, verifíquela comprobando la versión de Ansible:
ansible --version
Debería ver una salida similar a la siguiente, lo que confirma que Ansible está correctamente instalado:
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
Comprensión del Inventario de Ansible
Ansible necesita saber a qué hosts conectarse. Para este laboratorio, usaremos un archivo de inventario simple que incluye solo la máquina local.
Cree un directorio para nuestro proyecto de Ansible:
mkdir -p ~/project/ansible-lab
cd ~/project/ansible-lab
Ahora, cree un archivo de inventario llamado inventory.ini:
echo "localhost ansible_connection=local" > inventory.ini
Este archivo de inventario le dice a Ansible que ejecute comandos en la máquina local sin usar SSH.
Creación de su Primer Playbook
Ahora, creemos un playbook básico de Ansible. En el WebIDE, cree un nuevo archivo llamado first_playbook.yml en el directorio ~/project/ansible-lab con el siguiente contenido:
---
- 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 }}"
Este sencillo playbook tiene dos tareas:
- Mostrar un mensaje de saludo simple
- Mostrar información sobre el sistema operativo que está ejecutando
Ejecutemos este playbook para ver cómo funciona:
cd ~/project/ansible-lab
ansible-playbook -i inventory.ini first_playbook.yml
Debería ver una salida similar a esta:
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
Esta salida muestra:
- El playbook se ejecutó con éxito
- Todas las tareas se completaron con el estado "ok"
- La salida de cada tarea de depuración se muestra
Ahora que tenemos un playbook básico funcionando, podemos explorar cómo ejecutar scripts y mostrar su salida con más detalle.
Ejecución de Scripts y Captura de Salida
Ahora que tenemos un entorno básico de Ansible configurado, exploremos cómo ejecutar scripts y capturar su salida utilizando los módulos command y shell.
La Diferencia entre los Módulos Command y Shell
Ansible proporciona dos módulos principales para ejecutar comandos:
- command: Ejecuta un comando en un nodo remoto sin pasar por un shell, lo que significa que los operadores de shell como
|,>,<, y&no funcionan. - shell: Ejecuta un comando a través de un shell, lo que permite el uso de operadores de shell y variables de entorno.
Creación de un Script Simple para Ejecutar
Primero, creemos un script de shell simple que podamos ejecutar con Ansible. Cree un archivo llamado system_info.sh en su directorio ~/project/ansible-lab:
cd ~/project/ansible-lab
En el WebIDE, cree el archivo con el siguiente contenido:
#!/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"}')"
Haga que el script sea ejecutable:
chmod +x ~/project/ansible-lab/system_info.sh
Ahora, ejecutemos este script manualmente para ver qué salida produce:
./system_info.sh
Debería ver una salida similar a:
=== 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
Ejecución del Script con Ansible
Ahora, creemos un nuevo playbook que ejecutará este script y capturará su salida. Cree un archivo llamado script_output.yml en su directorio ~/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 }}"
Este playbook hace dos cosas:
- Ejecuta nuestro script
system_info.shutilizando el módulocommand - Almacena la salida en una variable llamada
script_resultutilizando la palabra claveregister - Muestra la salida capturada utilizando el módulo
debug
Ejecutemos este playbook:
cd ~/project/ansible-lab
ansible-playbook -i inventory.ini script_output.yml
Debería ver una salida similar a:
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
Observe cómo la salida aparece como una sola cadena con caracteres de nueva línea (\n). Mejoremos la visualización en la siguiente sección.
Comprensión de la Variable Register
La palabra clave register crea una variable que contiene varios atributos, no solo la salida del comando. Creemos un nuevo playbook para explorar estos atributos.
Cree un archivo llamado register_details.yml en su directorio ~/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
Ejecute este playbook:
ansible-playbook -i inventory.ini register_details.yml
Verá una salida más detallada que muestra todas las propiedades de la variable script_result, incluyendo:
stdout: La salida estándar como una sola cadenastderr: El error estándar (si lo hay)rc: El código de retorno (0 significa éxito)stdout_lines: La salida estándar dividida en una lista de líneas
La última tarea es particularmente útil ya que formatea la salida como una lista de líneas, haciéndola mucho más legible.
Técnicas Avanzadas de Manejo de Salida
Ahora que entendemos los conceptos básicos de la captura de la salida de scripts, exploremos algunas técnicas más avanzadas para manejar y mostrar la salida en los playbooks de Ansible.
Manejo de Errores de Script
Al ejecutar scripts, es importante manejar correctamente las condiciones de error. Ansible marca una tarea como fallida si el comando devuelve un código de salida distinto de cero. Creemos un playbook que demuestre el manejo de errores.
Cree un archivo llamado error_handling.yml en su directorio ~/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
En este playbook:
- Intentamos listar un directorio que no existe
- Usamos
ignore_errors: yespara evitar que el playbook se detenga si el comando falla - Verificamos el código de retorno (
cmd_result.rc) para determinar si el comando tuvo éxito o falló - Mostramos mensajes apropiados según el resultado
Ejecutemos este playbook:
cd ~/project/ansible-lab
ansible-playbook -i inventory.ini error_handling.yml
Debería ver una salida similar a:
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
Observe que, a pesar de que el comando falla, el playbook continúa ejecutándose y muestra el mensaje de error.
Formateo de Salida Multilínea
Creemos un script más complejo que genere una salida multilínea, luego formateémosla correctamente en nuestro playbook.
Cree un archivo llamado package_info.sh en su directorio ~/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
Hágalo ejecutable:
chmod +x ~/project/ansible-lab/package_info.sh
Ahora cree un playbook para ejecutar este script y formatear la salida correctamente. Cree un archivo llamado 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 }}
Este playbook:
- Ejecuta nuestro script
package_info.sh - Muestra la salida sin formato
- Usa una plantilla Jinja2 para formatear la salida con un título y un pie de página
Ejecutémoslo:
ansible-playbook -i inventory.ini formatted_output.yml
Debería ver una salida bien formateada:
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
Visualización Condicional de Salida
A veces, solo desea mostrar la salida bajo ciertas condiciones, como cuando se ejecuta en modo detallado. Veamos cómo hacer esto.
Cree un archivo llamado conditional_output.yml en su directorio ~/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
En este playbook:
- Capturamos la información de uso del disco
- Siempre mostramos un resumen (las dos primeras líneas)
- Mostramos los detalles completos solo cuando se ejecuta en modo detallado (con la bandera
-v)
Ejecutémoslo primero en modo normal:
ansible-playbook -i inventory.ini conditional_output.yml
Ahora, ejecutémoslo en modo detallado:
ansible-playbook -i inventory.ini conditional_output.yml -v
Notará que en modo detallado, obtiene la información completa del uso del disco, mientras que en modo normal, solo ve el resumen.
Esta técnica es útil para ocultar la salida potencialmente sensible o abrumadora de forma predeterminada, a la vez que la hace disponible cuando es necesaria para la depuración.
Resumen
En este laboratorio, ha aprendido varias técnicas para capturar y mostrar la salida de scripts en los playbooks de Ansible:
- Configuró un entorno básico de Ansible y creó su primer playbook
- Aprendió a ejecutar scripts utilizando los módulos
commandyshell - Capturó la salida del script utilizando la directiva
register - Mostró la salida utilizando el módulo
debugen diferentes formatos - Manejó las condiciones de error e implementó la visualización condicional de la salida
- Aplicó técnicas de formato para que la salida sea más legible
Estas habilidades le permiten crear playbooks de Ansible más informativos que proporcionen comentarios claros durante la ejecución. Esta visibilidad es crucial tanto para monitorear los procesos automatizados como para solucionar problemas cuando surgen.
Al aprovechar estas técnicas de manejo de salida, puede construir flujos de trabajo de automatización más robustos que no solo realizan tareas, sino que también comunican claramente lo que está sucediendo en cada paso. Esto hace que su automatización sea más transparente y fácil de mantener, especialmente cuando se trabaja en entornos de equipo o con infraestructuras complejas.


