Módulo Command de Ansible

AnsibleAnsibleBeginner
Practicar Ahora

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

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.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("Linux")) -.-> linux/BasicFileOperationsGroup(["Basic File Operations"]) ansible(("Ansible")) -.-> ansible/ModuleOperationsGroup(["Module Operations"]) linux(("Linux")) -.-> linux/FileandDirectoryManagementGroup(["File and Directory Management"]) ansible(("Ansible")) -.-> ansible/PlaybookEssentialsGroup(["Playbook Essentials"]) linux(("Linux")) -.-> linux/SystemInformationandMonitoringGroup(["System Information and Monitoring"]) linux/BasicFileOperationsGroup -.-> linux/ls("Content Listing") ansible/ModuleOperationsGroup -.-> ansible/command("Execute Commands") ansible/ModuleOperationsGroup -.-> ansible/debug("Test Output") linux/BasicFileOperationsGroup -.-> linux/tail("File End Display") linux/FileandDirectoryManagementGroup -.-> linux/pwd("Directory Displaying") ansible/PlaybookEssentialsGroup -.-> ansible/playbook("Execute Playbook") linux/SystemInformationandMonitoringGroup -.-> linux/df("Disk Space Reporting") linux/SystemInformationandMonitoringGroup -.-> linux/service("Service Managing") subgraph Lab Skills linux/ls -.-> lab-290161{{"Módulo Command de Ansible"}} ansible/command -.-> lab-290161{{"Módulo Command de Ansible"}} ansible/debug -.-> lab-290161{{"Módulo Command de Ansible"}} linux/tail -.-> lab-290161{{"Módulo Command de Ansible"}} linux/pwd -.-> lab-290161{{"Módulo Command de Ansible"}} ansible/playbook -.-> lab-290161{{"Módulo Command de Ansible"}} linux/df -.-> lab-290161{{"Módulo Command de Ansible"}} linux/service -.-> lab-290161{{"Módulo Command de Ansible"}} end

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: localhost especifica que el playbook se ejecutará en la máquina local.
  • La sección tasks contiene una lista de tareas a ejecutar.
  • La línea command: ls -l utiliza el módulo Command para ejecutar el comando ls -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 vars define 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 register guarda la salida del comando en una variable llamada command_output.
  • El módulo debug se utiliza para mostrar el contenido de la variable command_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.
  • async y poll: 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:

  1. Comprueba el estado del servicio SSH utilizando el comando service.
  2. Muestra el estado actual del servicio.
  3. Inicia el servicio si no está en ejecución.
  4. Verifica el estado del servicio después de la posible iniciación.
  5. Muestra el estado final del servicio.
  6. Comprueba si el puerto SSH (22) está a la escucha.
  7. 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:

  1. Crear playbooks simples de Ansible utilizando el módulo Command para ejecutar comandos básicos.
  2. Usar variables con el módulo Command para hacer que tus playbooks sean más flexibles y reutilizables.
  3. Capturar y procesar la salida de comandos, lo que te permite tomar decisiones basadas en los resultados de los comandos.
  4. Trabajar con varias opciones del módulo Command para controlar su comportamiento, como cambiar de directorio, establecer variables de entorno y manejar errores.
  5. 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.