Category Archives: Linux Script

Figlet as a Service

Todo comenzó cuando quise poner un ASCII Art a las máquinas para el fichero /etc/motd. Para hacerlo quería usar un playbook de Ansible que me permitiera generar el código ASCII utilizando como entrada en nombre del host.

Me puse a investigar y a sopesar las opciones:

  1. Podía instalar figlet en cada máquina y generar el ASCII Art.
  2. Podía usar alguna API que proporcionara algún método para obtener los ASCII Art en remoto

La primera opción no me convence porque tengo que instalar un paquete que solo se va a usar una vez y la segunda menos porque las opciones que encontré eran de pago y algunas máquinas no tienen salida a Internet.

Así pensé utilizar una combinación de ambas y crearme mi propio servicio de figlet. No ha sido demasiado complicado crearme un par de contenedores docker que para ofrecer el servicio a la infraestructura.

Dockerizando Figlet

Lo primero que hemos hecho ha sido buscar en Docker Hub el contenedor para PHP que ejecute FPM. Delante de este contenedor colocamos otro contenedor NGINX que actúa como frontend de la aplicación.

Esto no es complicado, porque ya está hecho, el hub oficial de PHP tiene un tag para FPM. A este contenedor hay que instalarle el paquete de figlet. Con apt se hace. Se escribe este cambio en el Dockerfile y se construye la imagen.

El contenedor de NGINX hay que configurarlo para que haga de proxy al php-fpm

Escribimos el código para leer la URL de la que sacaremos el nombre del host. Tenemos en cuenta si viene vacía, o si es mayor a 32 caracteres, ya que la RFC considera que el tamaño máximo de nombre de host es de 32 caracteres. También para este caso se pasa un ancho de columna a figlet de 160 caracteres, para que no salga cortado, en cualquier caso es raro que un nombre de host sobrepase los 15 caracteres, al menos en las infraestructuras que yo administro.

Construida la imagen, se escribe el docker-compose.yaml para vincular el nginx con el php-fpm. Se establece la política de restart, se exponen los puertos y se habilitan los volumenes.

Publicado

Está publicado aquí

Fuentes

Y las fuentes en mi github por si alguien quiere investigar o montarlo en su infraestructura.

Capturar Señales con Trap

Cuando estamos programando algún script puede interesarnos mandar señales mientras se está ejecutando. Para lograr que el script responda a las señales de kill utilizaremos la orden trap, que tiene la siguiente sintaxis.

trap acción señales

Los parámetros son:

  • acción: Definiremos que ejecutar cuando reciba la señal.
  • señales: Es la lista de señales ante las que responderá el script.

El principal uso de esto es controlar la salida de nuestro scripts, de forma que sea un cierre controlado, sin dejar archivos abiertos o temporales sin borrar.

Un ejemplo

#!/bin/bash

trap 'echo "Señal recibida"; exit' SIGKILL

while true
do
  echo "Soy un bucle"
done

En este caso cuando ejecutamos el script, si le enviamos un SIGKILL escribirá “Señal recibida” en el terminal y terminará.

En este punto también comentar que podemos usar varias lineas de trap para actuar de distinta forma ante distintas señales.

#!/bin/bash

trap 'echo "Señal SIGUSR1"; exit' SIGUSR1
trap 'echo "Señal SIGUSR2"; exit' SIGUSR2

while true
do
  echo "Soy un bucle"
done

Responderá diferente ante las señales SIGUSR1 y SIGUSR2.

Nombres de Archivos con Espacios a la Salida de find

Uso un script para ir eliminando viejos archivos de forma periódica a través de una tarea de Cron pero había empezado a fallar porque empezaban a aparecer nombres de ficheros con espacios. Al ocurrir esto, la salida que le pasaba a xargs y a su vez a rm fallaba. La solución viene en la página de manual.

$ man xargs
--null
-0     Input  items  are terminated by a null character instead of by whitespace, and the quotes and backslash are not special (every character is taken literally).
       Disables the end of file string, which is treated like any other argument.  Useful when input items might contain white space, quote marks,  or  backslashes.
       The GNU find -print0 option produces input suitable for this mode.

Perfectamente nos explica que debemos incluir el parámetro -print0 para que find genere una salida en la que por cada nombre de fichero se añada un carácter nulo, esto lo entenderá xargs que tomará el nombre del fichero completo incluyendo los espacios y caracteres especiales y se los pasará a rm que los borrará sin problema.

Así ha quedado el comando

TARGET="/path/to/files"
find $TARGET -maxdepth 1 -type f -name "*" -mtime +60 -print0 | xargs -0 rm;

Programar Encendido de PC

Hace un par de días publicaban en Linux.com un artículo que me gustó mucho, consistía en usar el RTC (Real Time Clock) de la placa base para programar el encendido del PC a través del pseudo-sistema de fichero /sys.

La idea se basa en escribir en uno de los pseudo ficheros la hora a la que se desea encender la máquina. No se necesita nada más.

Uno de los beneficios que no ofrece en nuestro día a día sería poder programar un apagado por algún mantenimiento que nosotros no controlamos (podrían cortar la luz para alguna reparación) y programar un encendido cuando estimemos que se ha terminado ese mantenimiento.

Para empezar debemos comprobar que nuestra versión de Kernel soporta rtc lo vemos así:

# grep -i rtc /boot/config-$(uname -r)

Que debe devolver:

[...]
CONFIG_HPET_EMULATE_RTC=y 
CONFIG_PM_TRACE_RTC=y 
CONFIG_RTC_LIB=y 
CONFIG_RTC_CLASS=y 
CONFIG_RTC_HCTOSYS=y 
CONFIG_RTC_HCTOSYS_DEVICE="rtc0" 
[...]

También es posible verlo a través de los logs del Kernel:

# grep -i rtc /var/log/messages 
# grep -i rtc /var/log/kern.log

Que debe salir:

Dec  2 08:14:38 asgard kernel: [    0.853916] rtc_cmos 00:03: RTC can wake from S4
Dec  2 08:14:38 asgard kernel: [    0.854031] rtc_cmos 00:03: rtc core: registered rtc_cmos as rtc0
Dec  2 08:14:38 asgard kernel: [    0.854053] rtc0: alarms up to one month, y3k, 114 bytes nvram, hpet irqs
Dec  2 08:14:38 asgard kernel: [    0.855641] rtc_cmos 00:03: setting system clock to 2012-12-02 07:14:23 UTC (1354432463)

Aquí muestra un par de cosas interesantes, la primera es que el reloj está sincronizado UTC e implica que no debemos tener en cuenta el cambio de horario de verano/invierno y que el dispositivo es rtc0, podría pasar, aunque es poco frecuente, que hubiera más de uno.

Probando

Ahora ya estamos listos para probar el invento, para ello solo necesitamos dos pasos:

Primero poner a cero el contador de la alarma:

# echo 0 > /sys/class/rtc/rtc0/wakealarm

Y segundo poner la alarma:

# echo $(date '+%s' -d '+ 3 minutes') > /sys/class/rtc/rtc0/wakealarm

Si ahora hacemos un cat del fichero veremos un número como este 1354444166 que es la fecha en formato epoch (segundos transcurridos desde el 1 de enero de 1970) y es el formato de tiempo que usa UNIX internamente.

Ahora podemos apagar el PC y ver como pasados los tres minutos arranca de nuevo.

A partir de aquí ya podemos escribir un script que simplifique la tarea, si queremos que se apague a cierta hora y se encienda de nuevo sin que tengamos que preocuparnos. O cosas así.

Referencia

Artículo original publicado por Carla Schroder en Linux.com con licencia Creative Commons 3.0

Ejecutar Comandos con un Usuario sin Shell Válida

Si tenemos en el sistema usuarios sin shell válida como por ejemplo los usuarios que acceden por FTP o que lanzan demonios y queremos ejecutar algún comando con ellos como por ejemplo actualizar su tabla de tareas de Cron, podemos hacerlo de la siguiente manera:

# su $USER -c comando -s /bin/bash

En este caso, ejecutara el comando bajo la shell bash.

Como hemos dicho, para alterar la tabla de Cron hacemos.

# su $USER -c "crontab -e" -s /bin/bash