Introducción
Ansible es una poderosa herramienta de automatización de código abierto ampliamente utilizada por administradores de sistemas y profesionales de DevOps. Una de sus capacidades clave es la ejecución de comandos de shell en hosts remotos y el procesamiento de su salida. En este tutorial práctico, aprenderá a capturar, mostrar y procesar eficazmente la salida de los comandos de shell en los playbooks de Ansible. Esta habilidad es esencial para crear flujos de trabajo de automatización robustos que puedan adaptarse a diferentes condiciones del sistema y proporcionar retroalimentación útil.
Configuración de su Primer Playbook de Ansible con Comandos de Shell
En este paso, configuraremos un playbook básico de Ansible que ejecuta comandos de shell y captura su salida. Esto proporcionará la base para técnicas más avanzadas en pasos posteriores.
Instalación de Ansible
Primero, instalemos Ansible en nuestro sistema:
sudo apt update
sudo apt install -y ansible
Ahora, verifique que Ansible esté instalado correctamente:
ansible --version
Debería ver una salida similar a esta:
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 15 2022, 12:22:08) [GCC 11.2.0]
jinja version = 3.0.3
libyaml = True
Creación de un Archivo de Inventario
Ansible utiliza un archivo de inventario para saber qué hosts administrar. Para este laboratorio, crearemos un inventario simple que incluye solo la máquina local:
- Abra su WebIDE y cree un nuevo archivo llamado
inventory.inien el directorio/home/labex/project. - Agregue el siguiente contenido al archivo:
[local]
localhost ansible_connection=local
Este inventario define un grupo llamado local que contiene solo el localhost, e indica a Ansible que se conecte directamente sin SSH.
Creación de su Primer Playbook
Ahora, creemos un playbook simple que ejecuta comandos de shell:
- Cree un nuevo archivo llamado
first_playbook.ymlen el directorio/home/labex/project. - Agregue el siguiente contenido YAML al archivo:
---
- name: Shell Command Example
hosts: local
gather_facts: no
tasks:
- name: Run a simple shell command
shell: echo "Hello from Ansible shell command"
register: hello_output
- name: Display the output
debug:
msg: "{{ hello_output.stdout }}"
Este playbook hace lo siguiente:
- Se dirige al grupo
localque definimos en nuestro inventario - Omite la recopilación de datos (información del sistema) para simplificar las cosas
- Ejecuta un comando de shell que muestra un mensaje de saludo
- Almacena la salida en una variable utilizando la palabra clave
register - Muestra la salida utilizando el módulo
debug
Ejecución de su Playbook
Ahora, ejecutemos el playbook:
ansible-playbook -i inventory.ini first_playbook.yml
Debería ver una salida similar a esta:
PLAY [Shell Command Example] **************************************************
TASK [Run a simple shell command] *********************************************
changed: [localhost]
TASK [Display the output] *****************************************************
ok: [localhost] => {
"msg": "Hello from Ansible shell command"
}
PLAY RECAP ********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
La salida muestra que nuestro playbook se ejecutó correctamente, ejecutando el comando de shell y mostrando su salida.
Conceptos Clave a Comprender
De este ejercicio, tenga en cuenta estos conceptos importantes:
- El módulo
shellle permite ejecutar comandos de shell - La directiva
registercaptura la salida de una tarea en una variable - El módulo
debugayuda a mostrar los valores de las variables - La salida del comando de shell contiene tanto
stdout(salida estándar) comostderr(salida de error)
En el siguiente paso, exploraremos cómo procesar y formatear la salida del comando de shell de manera más efectiva.
Trabajando con la Salida Estructurada de Comandos de Shell
Ahora que comprende los conceptos básicos de la ejecución de comandos de shell en Ansible, exploremos cómo trabajar con la salida estructurada de comandos y mostrarla en diferentes formatos.
Procesamiento de Información del Sistema
Creemos un playbook más práctico que recopile información del sistema y la presente de forma estructurada:
- Cree un nuevo archivo llamado
system_info.ymlen el directorio/home/labex/project. - Agregue el siguiente contenido:
---
- name: Gather and Display System Information
hosts: local
gather_facts: no
tasks:
- name: Gather system information
shell: |
echo "OS Information: $(cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2)"
echo "Kernel Version: $(uname -r)"
echo "CPU Information: $(grep "model name" /proc/cpuinfo | head -1 | cut -d: -f2 | xargs)"
echo "Memory Information: $(free -h | grep Mem | awk '{print $2}')"
register: system_info
- name: Display raw system information
debug:
msg: "{{ system_info.stdout }}"
- name: Display information as a list
debug:
msg: "{{ system_info.stdout_lines }}"
Este playbook:
- Ejecuta un script de shell de varias líneas que recopila varios detalles del sistema
- Almacena la salida en la variable
system_info - Muestra la salida primero como una cadena sin formato y luego como una lista de líneas
Ejecute el playbook:
ansible-playbook -i inventory.ini system_info.yml
Debería ver una salida que se parece a esto:
PLAY [Gather and Display System Information] **********************************
TASK [Gather system information] **********************************************
changed: [localhost]
TASK [Display raw system information] *****************************************
ok: [localhost] => {
"msg": "OS Information: \"Ubuntu 22.04.1 LTS\"\nKernel Version: 5.15.0-1023-azure\nCPU Information: Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz\nMemory Information: 4.0Gi"
}
TASK [Display information as a list] *****************************************
ok: [localhost] => {
"msg": [
"OS Information: \"Ubuntu 22.04.1 LTS\"",
"Kernel Version: 5.15.0-1023-azure",
"CPU Information: Intel(R) Xeon(R) Platinum 8171M CPU @ 2.60GHz",
"Memory Information: 4.0Gi"
]
}
PLAY RECAP ********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Observe cómo la segunda tarea de visualización muestra la salida como una lista en lugar de una cadena con saltos de línea. Este formato de lista facilita el trabajo con la salida de varias líneas.
Trabajando con Resultados de Comandos y Códigos de Retorno
Los comandos de shell en Linux devuelven códigos de salida para indicar éxito (0) o fracaso (distinto de cero). Ansible los captura en el atributo rc (código de retorno) de la variable registrada.
Creemos un playbook que demuestre cómo trabajar con códigos de retorno:
- Cree un nuevo archivo llamado
command_results.ymlen el directorio/home/labex/project. - Agregue el siguiente contenido:
---
- name: Working with Command Results
hosts: local
gather_facts: no
tasks:
- name: Check if a file exists
shell: test -f /etc/hosts
register: file_check
ignore_errors: yes
- name: Show command result details
debug:
msg: |
Return code: {{ file_check.rc }}
Succeeded: {{ file_check.rc == 0 }}
Failed: {{ file_check.rc != 0 }}
- name: Check if a non-existent file exists
shell: test -f /file/does/not/exist
register: missing_file
ignore_errors: yes
- name: Show command result for missing file
debug:
msg: |
Return code: {{ missing_file.rc }}
Succeeded: {{ missing_file.rc == 0 }}
Failed: {{ missing_file.rc != 0 }}
Este playbook:
- Ejecuta dos comandos de prueba para verificar si existen archivos
- Utiliza
ignore_errors: yespara evitar que el playbook se detenga si un comando falla - Muestra información detallada sobre los resultados del comando, incluido el código de retorno y el estado de éxito/fracaso
Ejecute el playbook:
ansible-playbook -i inventory.ini command_results.yml
Debería ver una salida similar a esta:
PLAY [Working with Command Results] *******************************************
TASK [Check if a file exists] *************************************************
changed: [localhost]
TASK [Show command result details] ********************************************
ok: [localhost] => {
"msg": "Return code: 0\nSucceeded: True\nFailed: False\n"
}
TASK [Check if a non-existent file exists] ************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "test -f /file/does/not/exist", "delta": "0:00:00.003183", "end": "2023-07-14 15:24:33.931406", "msg": "non-zero return code", "rc": 1, "start": "2023-07-14 15:24:33.928223", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring
TASK [Show command result for missing file] ***********************************
ok: [localhost] => {
"msg": "Return code: 1\nSucceeded: False\nFailed: True\n"
}
PLAY RECAP ********************************************************************
localhost : ok=4 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
Observe cómo el código de retorno es 0 para el archivo existente y 1 para el archivo no existente. Esto demuestra cómo puede usar los códigos de retorno para tomar decisiones en sus playbooks.
Comprensión de la Estructura de la Variable Registrada
La variable registrada desde un comando de shell contiene varios atributos útiles:
stdout: La salida estándar como una sola cadenastdout_lines: La salida estándar dividida en una lista de líneasstderr: La salida de error estándar como una sola cadenastderr_lines: La salida de error estándar dividida en una lista de líneasrc: El código de retorno (0 para éxito, distinto de cero para fracaso)cmd: El comando que se ejecutóstartyend: Marcas de tiempo para cuando el comando comenzó y terminódelta: La duración de la ejecución del comando
Comprender esta estructura es crucial para trabajar eficazmente con la salida de comandos de shell en Ansible.
Ejecución Condicional Basada en la Salida del Shell
Una de las capacidades más poderosas de Ansible es la capacidad de tomar decisiones basadas en la salida de los comandos de shell. En este paso, aprenderemos a usar condiciones y filtros para procesar la salida de los comandos de shell y hacer que los playbooks sean más dinámicos.
Uso de Condiciones con la Salida del Shell
Creemos un playbook que tome decisiones basadas en la salida del comando de shell:
- Cree un nuevo archivo llamado
conditional_playbook.ymlen el directorio/home/labex/project. - Agregue el siguiente contenido:
---
- name: Conditional Tasks Based on Command Output
hosts: local
gather_facts: no
tasks:
- name: Check disk space
shell: df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//'
register: disk_usage
- name: Display disk usage
debug:
msg: "Current disk usage: {{ disk_usage.stdout }}%"
- name: Disk usage warning
debug:
msg: "WARNING: Disk usage is high"
when: disk_usage.stdout|int > 50
- name: Disk usage normal
debug:
msg: "Disk usage is normal"
when: disk_usage.stdout|int <= 50
Este playbook:
- Ejecuta un comando de shell para verificar el porcentaje de uso del disco en el sistema de archivos raíz
- Utiliza la condición
whenbasada en la salida del comando - Utiliza el filtro
intpara convertir la salida de la cadena en un entero para la comparación
Ejecute el playbook:
ansible-playbook -i inventory.ini conditional_playbook.yml
La salida variará según el uso real de su disco, pero se verá algo como esto:
PLAY [Conditional Tasks Based on Command Output] ******************************
TASK [Check disk space] *******************************************************
changed: [localhost]
TASK [Display disk usage] *****************************************************
ok: [localhost] => {
"msg": "Current disk usage: 38%"
}
TASK [Disk usage warning] *****************************************************
skipped: [localhost]
TASK [Disk usage normal] ******************************************************
ok: [localhost] => {
"msg": "Disk usage is normal"
}
PLAY RECAP ********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Observe cómo Ansible ejecutó solo una de las tareas condicionales en función del valor real del uso del disco.
Manejo de la Salida JSON de los Comandos
Muchas herramientas CLI modernas devuelven datos en formato JSON. Ansible tiene capacidades integradas para manejar la salida JSON:
- Cree un nuevo archivo llamado
json_output.ymlen el directorio/home/labex/project. - Agregue el siguiente contenido:
---
- name: Handling JSON Output
hosts: local
gather_facts: no
tasks:
- name: Create a JSON file for testing
copy:
dest: /tmp/services.json
content: |
{
"services": [
{
"name": "web",
"status": "running",
"port": 80
},
{
"name": "database",
"status": "stopped",
"port": 5432
},
{
"name": "cache",
"status": "running",
"port": 6379
}
]
}
- name: Read JSON file with shell
shell: cat /tmp/services.json
register: json_output
- name: Parse and display JSON content
debug:
msg: "{{ json_output.stdout | from_json }}"
- name: Extract and display service information
debug:
msg: "Service: {{ item.name }}, Status: {{ item.status }}, Port: {{ item.port }}"
loop: "{{ (json_output.stdout | from_json).services }}"
- name: Show only running services
debug:
msg: "Running service: {{ item.name }} on port {{ item.port }}"
loop: "{{ (json_output.stdout | from_json).services }}"
when: item.status == "running"
Este playbook:
- Crea un archivo JSON de muestra para la demostración
- Lee el archivo JSON con un comando de shell
- Utiliza el filtro
from_jsonpara analizar la cadena JSON en una estructura de datos - Itera a través de la estructura de datos para mostrar información
- Utiliza la lógica condicional para filtrar solo los servicios en ejecución
Ejecute el playbook:
ansible-playbook -i inventory.ini json_output.yml
Debería ver una salida similar a esta:
PLAY [Handling JSON Output] ***************************************************
TASK [Create a JSON file for testing] *****************************************
changed: [localhost]
TASK [Read JSON file with shell] **********************************************
changed: [localhost]
TASK [Parse and display JSON content] *****************************************
ok: [localhost] => {
"msg": {
"services": [
{
"name": "web",
"port": 80,
"status": "running"
},
{
"name": "database",
"port": 5432,
"status": "stopped"
},
{
"name": "cache",
"port": 6379,
"status": "running"
}
]
}
}
TASK [Extract and display service information] ********************************
ok: [localhost] => (item={'name': 'web', 'status': 'running', 'port': 80}) => {
"msg": "Service: web, Status: running, Port: 80"
}
ok: [localhost] => (item={'name': 'database', 'status': 'stopped', 'port': 5432}) => {
"msg": "Service: database, Status: stopped, Port: 5432"
}
ok: [localhost] => (item={'name': 'cache', 'status': 'running', 'port': 6379}) => {
"msg": "Service: cache, Status: running, Port: 6379"
}
TASK [Show only running services] *********************************************
ok: [localhost] => (item={'name': 'web', 'status': 'running', 'port': 80}) => {
"msg": "Running service: web on port 80"
}
skipped: [localhost] => (item={'name': 'database', 'status': 'stopped', 'port': 5432})
ok: [localhost] => (item={'name': 'cache', 'status': 'running', 'port': 6379}) => {
"msg": "Running service: cache on port 6379"
}
PLAY RECAP ********************************************************************
localhost : ok=5 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Observe cómo el playbook analiza el JSON, extrae información específica y filtra los datos en función de las condiciones.
Manejo de Errores con Comandos de Shell
Al ejecutar comandos de shell, es importante manejar los posibles errores con elegancia:
- Cree un nuevo archivo llamado
error_handling.ymlen el directorio/home/labex/project. - Agregue el siguiente contenido:
---
- name: Error Handling with Shell Commands
hosts: local
gather_facts: no
tasks:
- name: Run a potentially failing command
shell: grep "nonexistent_pattern" /etc/passwd
register: command_result
ignore_errors: yes
- name: Display success or failure
debug:
msg: "Command {{ 'succeeded' if command_result.rc == 0 else 'failed with return code ' + command_result.rc|string }}"
- name: Run a custom failing command
shell: exit 3
register: exit_command
ignore_errors: yes
- name: Display detailed error information
debug:
msg: |
Return code: {{ exit_command.rc }}
Error message: {{ exit_command.stderr if exit_command.stderr else 'No error message' }}
Este playbook:
- Ejecuta comandos que se espera que fallen
- Utiliza
ignore_errors: yespara continuar la ejecución del playbook incluso cuando los comandos fallan - Muestra diferentes métodos para manejar y mostrar información de error
Ejecute el playbook:
ansible-playbook -i inventory.ini error_handling.yml
Debería ver una salida similar a esta:
PLAY [Error Handling with Shell Commands] *************************************
TASK [Run a potentially failing command] **************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "grep \"nonexistent_pattern\" /etc/passwd", "delta": "0:00:00.002916", "end": "2023-07-14 16:10:23.671519", "msg": "non-zero return code", "rc": 1, "start": "2023-07-14 16:10:23.668603", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring
TASK [Display success or failure] *********************************************
ok: [localhost] => {
"msg": "Command failed with return code 1"
}
TASK [Run a custom failing command] *******************************************
fatal: [localhost]: FAILED! => {"changed": true, "cmd": "exit 3", "delta": "0:00:00.002447", "end": "2023-07-14 16:10:23.906121", "msg": "non-zero return code", "rc": 3, "start": "2023-07-14 16:10:23.903674", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring
TASK [Display detailed error information] *************************************
ok: [localhost] => {
"msg": "Return code: 3\nError message: No error message\n"
}
PLAY RECAP ********************************************************************
localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=2
Esto demuestra cómo capturar y responder a diferentes condiciones de error al ejecutar comandos de shell.
Creación de una Herramienta Práctica de Procesamiento de Salida de Shell
En este paso final, reuniremos todo lo que hemos aprendido para crear un playbook de Ansible práctico que recopila información del sistema, la procesa y genera un informe. Esto representa un escenario del mundo real donde las capacidades de procesamiento de comandos de shell de Ansible pueden ser extremadamente útiles.
Construyendo una Herramienta de Informes de Información del Sistema
Creemos una herramienta completa de recopilación de información del sistema:
- Cree un nuevo archivo llamado
system_report.ymlen el directorio/home/labex/project. - Agregue el siguiente contenido:
---
- name: Comprehensive System Report
hosts: local
gather_facts: no
vars:
report_file: /tmp/system_report.txt
tasks:
- name: Collect basic system information
shell: |
echo "SYSTEM REPORT" > {{ report_file }}
echo "=============" >> {{ report_file }}
echo "" >> {{ report_file }}
echo "HOSTNAME: $(hostname)" >> {{ report_file }}
echo "TIMESTAMP: $(date)" >> {{ report_file }}
echo "" >> {{ report_file }}
echo "SYSTEM INFORMATION" >> {{ report_file }}
echo "------------------" >> {{ report_file }}
echo "OS: $(cat /etc/os-release | grep PRETTY_NAME | cut -d= -f2)" >> {{ report_file }}
echo "KERNEL: $(uname -r)" >> {{ report_file }}
echo "UPTIME: $(uptime -p)" >> {{ report_file }}
echo "" >> {{ report_file }}
echo "RESOURCE UTILIZATION" >> {{ report_file }}
echo "-------------------" >> {{ report_file }}
echo "CPU LOAD: $(uptime | awk -F'load average:' '{print $2}')" >> {{ report_file }}
echo "MEMORY USAGE:" >> {{ report_file }}
free -h >> {{ report_file }}
echo "" >> {{ report_file }}
echo "DISK USAGE:" >> {{ report_file }}
df -h >> {{ report_file }}
echo "" >> {{ report_file }}
echo "NETWORK INFORMATION" >> {{ report_file }}
echo "-------------------" >> {{ report_file }}
echo "IP ADDRESSES:" >> {{ report_file }}
ip addr | grep "inet " | awk '{print $2}' >> {{ report_file }}
echo "" >> {{ report_file }}
echo "PROCESS INFORMATION" >> {{ report_file }}
echo "-------------------" >> {{ report_file }}
echo "TOP 5 CPU CONSUMING PROCESSES:" >> {{ report_file }}
ps aux --sort=-%cpu | head -6 >> {{ report_file }}
echo "" >> {{ report_file }}
echo "TOP 5 MEMORY CONSUMING PROCESSES:" >> {{ report_file }}
ps aux --sort=-%mem | head -6 >> {{ report_file }}
register: report_generation
- name: Check if report was generated successfully
stat:
path: "{{ report_file }}"
register: report_stat
- name: Display report generation status
debug:
msg: "Report generated successfully at {{ report_file }}"
when: report_stat.stat.exists
- name: Display report content
shell: cat {{ report_file }}
register: report_content
when: report_stat.stat.exists
- name: Show report content
debug:
msg: "{{ report_content.stdout_lines }}"
when: report_stat.stat.exists
- name: Analyze disk usage
shell: df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//'
register: disk_usage
when: report_stat.stat.exists
- name: Generate disk usage alert if needed
debug:
msg: "ALERT: Disk usage on / is {{ disk_usage.stdout }}% which exceeds the 80% threshold!"
when:
- report_stat.stat.exists
- disk_usage.stdout|int > 80
- name: Generate disk usage warning if needed
debug:
msg: "WARNING: Disk usage on / is {{ disk_usage.stdout }}% which exceeds the 60% threshold."
when:
- report_stat.stat.exists
- disk_usage.stdout|int > 60
- disk_usage.stdout|int <= 80
- name: Confirm normal disk usage
debug:
msg: "Disk usage on / is normal at {{ disk_usage.stdout }}%."
when:
- report_stat.stat.exists
- disk_usage.stdout|int <= 60
Este playbook:
- Recopila información completa del sistema utilizando una serie de comandos de shell
- Escribe la información en un archivo de informe
- Verifica que el informe se creó correctamente
- Muestra el contenido del informe
- Analiza los datos de uso del disco
- Genera las alertas apropiadas en función del análisis
Ejecute el playbook:
ansible-playbook -i inventory.ini system_report.yml
Verá una salida completa que muestra la ejecución del playbook y el informe completo del sistema. La salida es bastante larga, por lo que aquí hay solo una muestra de lo que podría ver:
PLAY [Comprehensive System Report] ********************************************
TASK [Collect basic system information] ***************************************
changed: [localhost]
TASK [Check if report was generated successfully] *****************************
ok: [localhost]
TASK [Display report generation status] ***************************************
ok: [localhost] => {
"msg": "Report generated successfully at /tmp/system_report.txt"
}
TASK [Display report content] *************************************************
changed: [localhost]
TASK [Show report content] ****************************************************
ok: [localhost] => {
"msg": [
"SYSTEM REPORT",
"=============",
"",
"HOSTNAME: ubuntu-vm",
"TIMESTAMP: Fri Jul 14 16:35:42 UTC 2023",
"",
"SYSTEM INFORMATION",
"------------------",
"OS: \"Ubuntu 22.04.1 LTS\"",
"KERNEL: 5.15.0-1023-azure",
"UPTIME: up 3 hours, 25 minutes",
...
Examinando el Informe
Examinemos el informe del sistema que generamos:
cat /tmp/system_report.txt
Esto mostrará el informe completo que fue generado por nuestro playbook.
Creación de un Script de Shell Personalizado y Llamada desde Ansible
Para operaciones más complejas, a veces es más fácil crear un script de shell dedicado y llamarlo desde Ansible:
- Cree un nuevo archivo llamado
disk_analyzer.shen el directorio/home/labex/project. - Agregue el siguiente contenido:
#!/bin/bash
## disk_analyzer.sh - A simple script to analyze disk usage
echo "DISK USAGE ANALYSIS"
echo "------------------"
## Get overall disk usage
ROOT_USAGE=$(df -h / | grep -v Filesystem | awk '{print $5}' | sed 's/%//')
echo "Root filesystem usage: ${ROOT_USAGE}%"
## Categorize the usage
if [ $ROOT_USAGE -gt 80 ]; then
echo "STATUS: CRITICAL - Immediate action required"
elif [ $ROOT_USAGE -gt 60 ]; then
echo "STATUS: WARNING - Consider cleaning up disk space"
else
echo "STATUS: OK - Disk usage is within normal parameters"
fi
echo ""
## Find largest directories
echo "Top 5 largest directories in /var:"
du -h /var --max-depth=1 2> /dev/null | sort -hr | head -5
echo ""
## Find largest files
echo "Top 5 largest files in /var/log:"
find /var/log -type f -exec du -h {} \; 2> /dev/null | sort -hr | head -5
exit 0
- Haga que el script sea ejecutable:
chmod +x /home/labex/project/disk_analyzer.sh
- Cree un nuevo playbook para llamar a este script:
touch /home/labex/project/call_script.yml
- Agregue el siguiente contenido al playbook:
---
- name: Call Custom Shell Script
hosts: local
gather_facts: no
tasks:
- name: Run disk analyzer script
shell: /home/labex/project/disk_analyzer.sh
register: script_output
- name: Display script output
debug:
msg: "{{ script_output.stdout_lines }}"
- name: Check for critical status
debug:
msg: "CRITICAL DISK USAGE DETECTED! Immediate action required."
when: script_output.stdout is search("STATUS: CRITICAL")
- Ejecute el playbook:
ansible-playbook -i inventory.ini call_script.yml
Debería ver una salida similar a esta:
PLAY [Call Custom Shell Script] ***********************************************
TASK [Run disk analyzer script] ***********************************************
changed: [localhost]
TASK [Display script output] **************************************************
ok: [localhost] => {
"msg": [
"DISK USAGE ANALYSIS",
"------------------",
"Root filesystem usage: 38%",
"STATUS: OK - Disk usage is within normal parameters",
"",
"Top 5 largest directories in /var:",
"60M\t/var/lib",
"60M\t/var/cache",
"12M\t/var/log",
"4.0K\t/var/tmp",
"4.0K\t/var/mail",
"",
"Top 5 largest files in /var/log:",
"4.0M\t/var/log/journal/c75af53674ce472fb9654a1d5cf8cc37/system.journal",
"2.3M\t/var/log/auth.log",
"1.3M\t/var/log/syslog",
"724K\t/var/log/kern.log",
"428K\t/var/log/cloud-init.log"
]
}
TASK [Check for critical status] **********************************************
skipped: [localhost]
PLAY RECAP ********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Este enfoque combina el poder de los scripts de shell con las capacidades de automatización de Ansible. El script de shell maneja la lógica compleja para el análisis del disco, mientras que Ansible gestiona la ejecución y el procesamiento posterior de los resultados.
Conclusiones Clave
A través de este laboratorio, ha aprendido varias técnicas importantes para trabajar con la salida de comandos de shell en Ansible:
- Cómo ejecutar comandos de shell y capturar su salida
- Cómo procesar y formatear la salida de comandos para mostrarla
- Cómo utilizar la ejecución condicional basada en los resultados de los comandos
- Cómo manejar la salida JSON y las condiciones de error
- Cómo crear herramientas prácticas que combinan comandos de shell con las capacidades de automatización de Ansible
Estas habilidades serán invaluables a medida que construya soluciones de automatización más complejas con Ansible.
Resumen
En este laboratorio, aprendió a trabajar eficazmente con la salida de comandos de shell en los playbooks de Ansible. Comenzando con los conceptos básicos de la ejecución de comandos de shell y la captura de su salida, progresó a técnicas más avanzadas como la ejecución condicional, el manejo de errores y el procesamiento de formatos de datos estructurados como JSON.
Ha dominado varias habilidades clave:
- Ejecutar comandos de shell en los playbooks de Ansible utilizando el módulo
shell - Capturar la salida del comando con la directiva
register - Mostrar la salida utilizando el módulo
debug - Procesar la salida con filtros y condicionales de Jinja2
- Crear herramientas de automatización prácticas que combinan Ansible con scripts de shell
Estas técnicas le permiten crear flujos de trabajo de automatización más dinámicos y receptivos que pueden adaptarse a diferentes condiciones del sistema y proporcionar comentarios útiles sobre las operaciones que se están realizando.
A medida que continúa su viaje con Ansible, recuerde que, si bien los comandos de shell brindan una gran flexibilidad, los módulos integrados de Ansible son a menudo una solución más robusta y portátil para las tareas comunes. Use comandos de shell cuando necesite aprovechar los scripts de shell existentes o realizar operaciones complejas que no se manejan fácilmente con los módulos de Ansible.


