Ejecución de comandos en servidores remotos con el módulo Ansible Shell
Ansible es una herramienta de gestión de configuraciones ampliamente utilizada que simplifica la gestión de múltiples servidores. Optimiza tareas como la configuración de servidores y la instalación de aplicaciones mediante la automatización, lo que te permite gestionar numerosos servidores remotos y ejecutar tareas de forma secuencial desde un nodo central. Además, Ansible es popular por sus numerosos módulos y su capacidad para funcionar a la perfección a través de SSH sin necesidad de instalar software adicional en los servidores de destino.
En este tutorial, aprenderemos a ejecutar comandos en servidores remotos con el módulo Ansible Shell. Además, también exploraremos cómo ejecutar comandos ad hoc de Ansible y crear un playbook para ejecutar diferentes comandos de shell.
Requisitos previos
Para usar el módulo shell de Ansible necesitas:
- En esta guía, utilizamos Ubuntu 22.04. Ansible debe estar instalado y configurado en tu sistema.
- Un host remoto configurado en el que ejecutarás los comandos utilizando el módulo de shell de Ansible.
¿Qué es el módulo de shell de Ansible?
El módulo de shell de Ansible permite a los usuarios ejecutar comandos en el shell de los sistemas de destino. Permite a los usuarios ejecutar comandos complejos con tuberías y redireccionamiento en destinos remotos que mantienen la originalidad de la ejecución del comando.
Al ejecutar comandos en el módulo de shell de Ansible, toma el nombre del comando, los parámetros o los argumentos separados por delimitadores de espacio en blanco y ejecuta estos comandos en los hosts remotos.
Diferencia: módulo de shell de Ansible frente al módulo de comando
Tanto el módulo de shell de Ansible como el módulo de comando son bastante similares y dan los mismos resultados. Sin embargo, existen algunas diferencias entre estos dos módulos que hemos enumerado a continuación:
- El módulo shell de Ansible admite todos los operadores especiales, variables de entorno, tuberías y redirecciones. Por el contrario, los módulos de comando no admiten los operadores (<, >, &,;, | |), las variables de entorno ni las tuberías.
- El módulo de comando no permite a los usuarios ejecutar comandos directamente en el shell. En este caso, el módulo shell de Ansible ofrece más flexibilidad que el módulo de comando. Con el módulo shell, puedes ejecutar comandos directamente en el shell de los hosts de destino. Utiliza el shell «/bin/sh» de forma predeterminada para ejecutar comandos. También puedes configurar otros shells para ejecutar comandos en hosts remotos.
- Los usuarios de Ansible prefieren utilizar módulos de comando en términos de seguridad al ejecutar comandos en sistemas de destino. Los comandos ejecutados por Ansible en el módulo de comando son más seguros y ofrecen opciones más predecibles que el módulo de shell de Ansible. Además, el módulo de comando no afecta al entorno de shell remoto del usuario.
Introducción a los comandos de shell de Ansible: ejecutar comandos ad hoc
Los comandos ad hoc son comandos de una sola línea que no se pueden reutilizar en el futuro. Sin embargo, puedes usar los comandos ad hoc de Ansible para ejecutar rápidamente tareas individuales. A continuación se muestra la sintaxis básica de los comandos ad hoc:
ansible [patrón] -m [módulo de Ansible] -a {comandos con opciones}
En la sintaxis anterior, el patrón representa el grupo de hosts al que pertenece el host de destino. La opción «-m» especifica el tipo de módulo y la opción «-a» toma los argumentos del comando.
Veamos un ejemplo para explicar la sintaxis del comando ad hoc de Ansible. En este ejemplo, intentaremos mostrar la fecha y la hora del host de destino. Aquí, solo nos hemos conectado a un host y hemos creado un usuario independiente, «ansible». Usa el siguiente comando para mostrar la fecha y la hora del host remoto:
$ ansible 192.168.1.14 -u ansible -m shell -a "timedatectl"
El comando ad-hoc de Ansible anterior se conectará al host remoto en la dirección IP «192.168.1.14» utilizando el nombre de usuario «ansible» a través de SSH. A continuación, se ejecutará el comando «timedatectl» en el host remoto, que se utiliza para mostrar información sobre la configuración de fecha y hora del sistema.
$ ansible <dirección IP> -u ansible -m shell -a "timedatectl | grep Time"
Con el comando ad hoc de Ansible anterior, se ejecutará el comando «timedatectl» y, a continuación, utilizando el comando grep, se filtrarán y mostrarán las líneas que contengan «Time».
Del mismo modo, puedes ver el tiempo de actividad y la carga media del sistema con el comando «uptime»:
$ ansible <dirección IP> -u ansible -m shell -a "uptime"
Al ejecutar este comando, se ejecutará el comando uptime después de conectarse al host remoto.
$ ansible <dirección IP> -u ansible -m setup
El módulo setup recopila los datos (facts) del sistema remoto: sistema operativo, red, memoria, discos, etc. Fíjate en que aquí no se usa el módulo shell, sino setup directamente.
¿Cómo se utiliza el módulo de shell de Ansible?
Antes de ejecutar los comandos de shell de Ansible, conviene conocer sus parámetros básicos:
chdir: cambia el directorio actual antes de ejecutar el comando.
cmd: una cadena que contiene el comando que se va a ejecutar, junto con los argumentos asociados.
executable: requiere una ruta absoluta para cambiar el shell que está utilizando el usuario.
removes: toma el nombre del archivo y se utiliza para excluir pasos cuando un archivo no existe.
stdin: permite al usuario establecer el «stdin» de un comando en un valor específico.
warn: sí o no, habilitaba o deshabilitaba las advertencias de la tarea (este parámetro se eliminó en Ansible 2.14).
Una vez aclarado esto, veamos algunos ejemplos de cómo utilizar el shell de Ansible.
Ejecutar comandos con el módulo Shell de Ansible
La verdadera potencia de Ansible reside en el uso de playbooks, que permiten realizar tareas avanzadas en los hosts de destino. Además de utilizar comandos ad hoc, también puedes usar el módulo shell dentro de los playbooks para definir tareas para hosts remotos.
Ejecutar un solo comando con el módulo shell de Ansible
Para ejecutar un solo comando con el módulo shell, crea un playbook, por ejemplo single_command.yml, y pega estas líneas:
- name: Ejemplo del módulo shell
hosts: database_servers
tasks:
- name: Comprobar el uso del disco
shell: df -h
register: os_info
- debug:
msg: "{{ os_info.stdout_lines }}"
Guarda los cambios con «Ctrl+O», sal con «Ctrl+X» y ejecuta el playbook (el nombre del archivo debe coincidir con el que acabas de crear):
$ ansible-playbook -i hosts single_command.yml
La tarea debug mostrará en la terminal la salida de df -h del host remoto.
Ansible ejecuta varios comandos con el módulo Shell
Puedes ejecutar varias tareas de forma secuencial. Para crear el playbook, abre un archivo nuevo con el editor nano:
$ nano testplaybook.yml
Pega en él el siguiente contenido:
- name: Crear usuario e instalar Nginx
hosts: database_servers
become: yes
vars:
username: deploy
package: nginx
tasks:
- name: Crear el usuario
user:
name: "{{ username }}"
state: present
shell: /bin/bash
- name: Actualizar la caché de paquetes
apt:
update_cache: yes
- name: Instalar o actualizar Nginx
apt:
name: "{{ package }}"
state: latest
Este playbook crea un usuario, actualiza la caché de paquetes e instala o actualiza Nginx en el host remoto. Usa variables para que sea más flexible y reutilizable.
Guarda el archivo con «Ctrl+O» y sal con «Ctrl+X».
Aquí estamos utilizando el archivo de inventario personalizado «hosts». Para ejecutar este playbook, usa el siguiente comando:
$ ansible-playbook --ask-become-pass -i hosts testplaybook.yml
La opción «--ask-become-pass» te pedirá la contraseña de sudo del usuario remoto, necesaria porque el playbook usa become: yes.
Instalar un paquete con el módulo Ansible Shell
También puedes instalar paquetes en el host remoto. Este playbook instala «apache2» (para instalar paquetes es mejor usar el módulo apt que el módulo shell):
- name: Instalar Apache
hosts: database_servers
become: yes
tasks:
- name: Actualizar la caché de paquetes
apt:
update_cache: yes
- name: Instalar el paquete apache2
apt:
name: apache2
state: present
Después de ejecutarlo, apache2 quedará instalado en los servidores remotos.
Evitar la inyección de comandos Shell
Como hemos comentado anteriormente, el módulo de comandos de Ansible se considera una opción más segura para ejecutar comandos en sistemas remotos. Sin embargo, tiene ciertas limitaciones en cuanto a funcionalidad.
Para usar el módulo shell de forma segura, aplica el filtro quote a las variables que insertas en el comando: las entrecomilla para la shell y evita la inyección de comandos. Por ejemplo:
- name: Ejemplo del filtro quote de Ansible
hosts: database_servers
become: yes
vars:
database_name: mydb
sql: "CREATE TABLE my_table (id INT, name VARCHAR(255));"
tasks:
- name: Crear una tabla en la base de datos {{ database_name }}
shell: mysql -u root -psecret {{ database_name | quote }} -e {{ sql | quote }}
Este playbook crea una tabla MySQL en la base de datos indicada. Gracias al filtro quote, aunque el valor de las variables contenga espacios o caracteres especiales, la shell lo recibirá como un único argumento.
Conclusión
El módulo de shell de Ansible es una herramienta flexible y robusta que mejora el control del usuario y simplifica las configuraciones de servidores remotos. En este artículo, hemos explorado cómo utilizar el módulo de shell de Ansible, sus parámetros y los argumentos necesarios. Esperamos que con estos conocimientos puedas usar el módulo shell de Ansible con eficacia en tus servidores Linux.
Blog