Introducción
En este laboratorio, explorarás el módulo Command de Ansible, una herramienta poderosa para ejecutar comandos en hosts remotos. El módulo Command te permite interactuar con la línea de comandos directamente desde tus playbooks y tareas de Ansible, ofreciendo una forma versátil de administrar sistemas remotos. A lo largo de este laboratorio, aprenderás cómo usar el módulo Command de Ansible para ejecutar varios comandos, trabajar con variables y argumentos, y capturar la salida de los comandos.
Crear un playbook simple de Ansible
En este paso, crearás tu primer playbook de Ansible utilizando el módulo Command para ejecutar un comando simple.
Primero, navega hasta el directorio del proyecto:
cd ~/project
Ahora, crea un nuevo archivo llamado simple_command.yml utilizando el editor de texto de tu elección. Por ejemplo, puedes usar el editor nano:
nano simple_command.yml
Agrega el siguiente contenido al archivo:
---
- name: Execute a simple command
hosts: localhost
tasks:
- name: Run 'ls' command
command: ls -l
Analicemos este playbook:
- La línea
hosts: localhostespecifica que el playbook se ejecutará en la máquina local. - La sección
taskscontiene una lista de tareas a ejecutar. - La línea
command: ls -lutiliza el módulo Command para ejecutar el comandols -l, que lista archivos y directorios en formato detallado.
Guarda el archivo y sal del editor (en nano, presiona Ctrl+X, luego Y, luego Enter).
Ahora, ejecuta el playbook con el siguiente comando:
ansible-playbook simple_command.yml
Deberías ver una salida similar a esta:
PLAY [Execute a simple command] ************************************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Run 'ls' command] ********************************************************
changed: [localhost]
PLAY RECAP *********************************************************************
localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Esta salida indica que el playbook se ejecutó correctamente, ejecutando el comando ls -l en tu máquina local.
Usar variables con el módulo Command
En este paso, aprenderás cómo usar variables con el módulo Command de Ansible. Las variables te permiten hacer que tus playbooks sean más flexibles y reutilizables.
Crea un nuevo archivo llamado variable_command.yml:
nano variable_command.yml
Agrega el siguiente contenido al archivo:
---
- name: Use variables with the Command module
hosts: localhost
vars:
file_path: /etc/passwd
line_count: 5
tasks:
- name: Display the last few lines of a file
command: "tail -n {{ line_count }} {{ file_path }}"
register: command_output
- name: Show the command output
debug:
var: command_output.stdout_lines
Este playbook introduce varios conceptos nuevos:
- La sección
varsdefine variables que se pueden usar en todo el playbook. - Usamos la sintaxis
{{ variable_name }}para hacer referencia a variables dentro del comando. - La palabra clave
registerguarda la salida del comando en una variable llamadacommand_output. - El módulo
debugse utiliza para mostrar el contenido de la variablecommand_output.
Guarda el archivo y sal del editor.
Ahora, ejecuta el playbook:
ansible-playbook variable_command.yml
Deberías ver una salida similar a esta:
PLAY [Use variables with the Command module] ***********************************
TASK [Gathering Facts] *********************************************************
ok: [localhost]
TASK [Display the last few lines of a file] ************************************
changed: [localhost]
TASK [Show the command output] *************************************************
ok: [localhost] => {
"command_output.stdout_lines": [
"games:x:5:60:games:/usr/games:/usr/sbin/nologin",
"man:x:6:12:man:/var/cache/man:/usr/sbin/nologin",
"lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin",
"mail:x:8:8:mail:/var/mail:/usr/sbin/nologin",
"news:x:9:9:news:/var/spool/news:/usr/sbin/nologin"
]
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Esta salida muestra las últimas 5 líneas del archivo /etc/passwd, lo que demuestra cómo se pueden usar variables con el módulo Command.
Capturar y procesar la salida de comandos
En este paso, aprenderás cómo capturar la salida de un comando y procesarla adicionalmente utilizando Ansible.
Crea un nuevo archivo llamado process_output.yml:
nano process_output.yml
Agrega el siguiente contenido al archivo:
---
- name: Capture and process command output
hosts: localhost
tasks:
- name: Get disk usage information
command: df -h
register: df_output
- name: Display all partitions
debug:
msg: "{{ df_output.stdout_lines }}"
- name: Find root partition
set_fact:
root_partition: "{{ df_output.stdout_lines | select('match', '\\s+/$') | first | default('') }}"
- name: Display root partition information
debug:
msg: "Root partition: {{ root_partition }}"
when: root_partition!= ''
- name: Extract usage percentage
set_fact:
root_usage: "{{ root_partition.split()[-2].rstrip('%') | int }}"
when: root_partition!= ''
- name: Display root partition usage
debug:
msg: "Root partition is {{ root_usage }}% full"
when: root_partition!= ''
- name: Check if root partition is over 80% full
fail:
msg: "Warning: Root partition is over 80% full!"
when: root_partition!= '' and root_usage > 80
- name: Display message if root partition not found
debug:
msg: "Root partition (/) not found in df output"
when: root_partition == ''
Este playbook es más robusto y maneja casos en los que la partición raíz puede no ser fácilmente detectable:
- Mostramos todas las particiones para ver qué está disponible.
- Usamos un patrón más flexible para encontrar la partición raíz.
- Agregamos comprobaciones para manejar casos en los que la partición raíz no se encuentra.
- Usamos el filtro
default('')para evitar errores cuando la partición raíz no se encuentra.
Guarda el archivo y sal del editor.
Ahora, ejecuta el playbook:
ansible-playbook process_output.yml
Deberías ver una salida similar a esta:
PLAY [Capture and process command output] ************************************************
TASK [Gathering Facts] *******************************************************************
ok: [localhost]
TASK [Get disk usage information] ********************************************************
changed: [localhost]
TASK [Display all partitions] ************************************************************
ok: [localhost] => {
"msg": [
"Filesystem Size Used Avail Use% Mounted on",
"overlay 20G 618M 20G 4% /",
"tmpfs 64M 0 64M 0% /dev",
"tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup",
"shm 64M 128K 64M 1% /dev/shm",
"/dev/vdb 100G 17G 84G 17% /etc/hosts"
]
}
TASK [Find root partition] ***************************************************************
ok: [localhost]
TASK [Display root partition information] ************************************************
skipping: [localhost]
TASK [Extract usage percentage] **********************************************************
skipping: [localhost]
TASK [Display root partition usage] ******************************************************
skipping: [localhost]
TASK [Check if root partition is over 80% full] ******************************************
skipping: [localhost]
TASK [Display message if root partition not found] ***************************************
ok: [localhost] => {
"msg": "Root partition (/) not found in df output"
}
PLAY RECAP *******************************************************************************
localhost : ok=7 changed=1 unreachable=0 failed=1 skipped=1 rescued=0 ignored=0
Esta salida muestra todas las particiones, identifica la partición raíz y comprueba su uso. Los valores exactos pueden diferir en tu sistema.
Trabajar con opciones del módulo Command
En este paso, explorarás algunas de las opciones disponibles con el módulo Command de Ansible para controlar su comportamiento.
Crea un nuevo archivo llamado command_options.yml:
nano command_options.yml
Agrega el siguiente contenido al archivo:
---
- name: Explore Command module options
hosts: localhost
tasks:
- name: Run a command with a specific working directory
command: pwd
args:
chdir: /tmp
- name: Run a command with environment variables
command: echo $MY_VAR
environment:
MY_VAR: "Hello from Ansible"
- name: Run a command and ignore errors
command: ls /nonexistent_directory
ignore_errors: yes
- name: Run a command with a timeout
command: sleep 2
async: 5
poll: 0
register: sleep_result
- name: Check sleep command status
async_status:
jid: "{{ sleep_result.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 5
delay: 1
Este playbook demuestra varias opciones del módulo Command:
chdir: Cambia el directorio de trabajo antes de ejecutar el comando.environment: Establece variables de entorno para el comando.ignore_errors: Continúa la ejecución del playbook incluso si el comando falla.asyncypoll: Ejecuta el comando de forma asíncrona con un tiempo de espera.
Guarda el archivo y sal del editor.
Ahora, ejecuta el playbook:
ansible-playbook command_options.yml
Deberías ver una salida similar a esta:
PPLAY [Explore Command module options]
TASK [Gathering Facts]
ok: [localhost]
TASK [Run a command with a specific working directory]
changed: [localhost]
TASK [Run a command with environment variables]
changed: [localhost]
TASK [Run a command and ignore errors]
fatal: [localhost]: FAILED! => {"changed": true, "cmd": ["ls", "/nonexistent_directory"], "delta": "0:00:00.006113", "end": "2024-09-06 09:40:43.373350", "msg": "non-zero return code", "rc": 2, "start": "2024-09-06 09:40:43.367237", "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 [Run a command with a timeout]
changed: [localhost]
TASK [Check sleep command status]
FAILED - RETRYING: Check sleep command status (10 retries left).
FAILED - RETRYING: Check sleep command status (9 retries left).
FAILED - RETRYING: Check sleep command status (8 retries left).
FAILED - RETRYING: Check sleep command status (7 retries left).
FAILED - RETRYING: Check sleep command status (6 retries left).
FAILED - RETRYING: Check sleep command status (5 retries left).
FAILED - RETRYING: Check sleep command status (4 retries left).
FAILED - RETRYING: Check sleep command status (3 retries left).
FAILED - RETRYING: Check sleep command status (2 retries left).
FAILED - RETRYING: Check sleep command status (1 retries left).
fatal: [localhost]: FAILED! => {"ansible_job_id": "5877920468.2517", "attempts": 10, "changed": false, "finished": 0, "started": 1}
PLAY RECAP
Esta salida demuestra los diferentes comportamientos de las opciones del módulo Command que hemos explorado.
Usar el módulo Command en un escenario compatible con Docker
En este último paso, utilizarás el módulo Command de Ansible en un escenario más realista y compatible con Docker: comprobar el estado del servicio SSH y gestionarlo si es necesario.
Crea un nuevo archivo llamado check_service_docker.yml:
nano check_service_docker.yml
Agrega el siguiente contenido al archivo:
---
- name: Check and manage SSH service in Docker
hosts: localhost
become: yes ## This allows Ansible to use sudo
tasks:
- name: Check SSH service status
command: service ssh status
register: ssh_status
ignore_errors: yes
- name: Display SSH service status
debug:
msg: "SSH service status: {{ ssh_status.stdout }}"
- name: Start SSH service if not running
command: service ssh start
when: ssh_status.rc!= 0
- name: Verify SSH service is running
command: service ssh status
register: ssh_status_after
- name: Display final SSH service status
debug:
msg: "SSH service status is now: {{ ssh_status_after.stdout }}"
- name: Check if SSH port is listening
command: netstat -tuln | grep :22
register: ssh_port_check
ignore_errors: yes
- name: Display SSH port status
debug:
msg: "SSH port 22 is {{ 'open' if ssh_port_check.rc == 0 else 'closed' }}"
Este playbook realiza las siguientes acciones:
- Comprueba el estado del servicio SSH utilizando el comando
service. - Muestra el estado actual del servicio.
- Inicia el servicio si no está en ejecución.
- Verifica el estado del servicio después de la posible iniciación.
- Muestra el estado final del servicio.
- Comprueba si el puerto SSH (22) está a la escucha.
- Muestra el estado del puerto SSH.
Guarda el archivo y sal del editor.
Ahora, ejecuta el playbook con privilegios de sudo:
sudo ansible-playbook check_service_docker.yml
Deberías ver una salida similar a esta:
PLAY [Check and manage SSH service in Docker] *****************************************
TASK [Gathering Facts] ****************************************************************
ok: [localhost]
TASK [Check SSH service status] *******************************************************
changed: [localhost]
TASK [Display SSH service status] *****************************************************
ok: [localhost] => {
"msg": "SSH service status: * sshd is running"
}
TASK [Start SSH service if not running] ***********************************************
skipping: [localhost]
TASK [Verify SSH service is running] **************************************************
changed: [localhost]
TASK [Display final SSH service status] ***********************************************
ok: [localhost] => {
"msg": "SSH service status is now: * sshd is running"
}
TASK [Check if SSH port is listening] *************************************************
changed: [localhost]
TASK [Display SSH port status] ********************************************************
ok: [localhost] => {
"msg": "SSH port 22 is open"
}
PLAY RECAP ****************************************************************************
localhost : ok=6 changed=3 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Esta salida muestra que el servicio SSH ya estaba en ejecución, por lo que no era necesario iniciarlo. El playbook comprobó y verificó correctamente el estado del servicio y también confirmó que el puerto SSH está abierto.
Resumen
En este laboratorio, has explorado la versatilidad y el poder del módulo Command de Ansible. Has aprendido cómo:
- Crear playbooks simples de Ansible utilizando el módulo Command para ejecutar comandos básicos.
- Usar variables con el módulo Command para hacer que tus playbooks sean más flexibles y reutilizables.
- Capturar y procesar la salida de comandos, lo que te permite tomar decisiones basadas en los resultados de los comandos.
- Trabajar con varias opciones del módulo Command para controlar su comportamiento, como cambiar de directorio, establecer variables de entorno y manejar errores.
- Aplicar el módulo Command en un escenario del mundo real al comprobar y gestionar un servicio del sistema.
Estas habilidades forman una base sólida para utilizar Ansible para automatizar tareas de administración de sistemas y gestionar hosts remotos de manera eficiente. A medida que sigas trabajando con Ansible, encontrarás que el módulo Command es una herramienta versátil en tu conjunto de herramientas de automatización.
Recuerda que aunque el módulo Command es poderoso, a menudo es mejor utilizar módulos especializados de Ansible (como el módulo service para gestionar servicios) cuando estén disponibles. Estos módulos especializados ofrecen una mejor idempotencia y pueden manejar escenarios más complejos de forma inmediata.
Sigue practicando y explorando las capacidades de Ansible para mejorar aún más tus habilidades de automatización y optimizar tus operaciones de TI.


