Automatización de tareas y servicios#
Comando at#
Permite indicar el momento en que se quiere ejecutar un trabajo at [opciones ] TIME , para ver los trabajos utilizamos at -l y para borrarlos at -d como se puede ver en el siguiente ejemplo:
$ at 5:00 PM
at> ls
at> <EOT>
job 16 at Tue Nov 14 17:00:00 2023
$ at 7:00 PM
at> ls
at> <EOT>
job 17 at Tue Nov 14 19:00:00 2023
$ at -l
16 Tue Nov 14 17:00:00 2023 a dani
17 Tue Nov 14 19:00:00 2023 a dani
$ at -d 16
$ at -l
17 Tue Nov 14 19:00:00 2023 a dani
Al ejecutar at pasamos a un nuevo prompt, que nos permite introducir comandos que se ejecutarán a la hora indicada. Para guardar trabajo y salir: CTRL+D (guarda el entorno), el trabajo no para aunque se cierre la sesión.
Más opciones:
-f FILE # indica un fichero donde se encuentran las acciones a realizar.
HH:MM -> 12:54
HH:MMAM/PM, -> 1:35PM
HH:MM MMDDYY -> 1:35PM 122505
now + num -> at now+2hours
num puede ser minutos, horas, días, semanas, ...
today, tomorrow -> 22:44tomorrow
Control de acceso: /etc/at.allow, /etc/at.deny
Crontab#
Cron se emplea para ejecución de trabajos periódicos, utilizamos el comando crontab para configurar los procesos a ejecutar , para modificarlo utilizaremos:
crontab -e #edita el fichero crontab
crontab -l #muestra el fichero crontab
crontab -r #borra el fichero crontab
Ejemplo de lineas en el crontab:
01 * * * * date > ~/log
02 4 * * * /ruta/al/script.sh
Formato de Configuración: El formato general para programar tareas en crontab sigue este patrón: minuto hora díaDelMes mes díaDeLaSemana comando.
minuto: Minuto en el que se ejecutará la tarea (0-59).
hora: Hora en la que se ejecutará la tarea (0-23).
díaDelMes: Día del mes en el que se ejecutará la tarea (1-31).
mes: Mes en el que se ejecutará la tarea (1-12).
díaDeLaSemana: Día de la semana en el que se ejecutará la tarea (0-6, donde 0 es domingo).
comando: Comando o script que se ejecutará.
Ejemplos:
01 * * * * Se ejecuta al minuto 1 de cada hora de todos los días
15 8 * * * A las 8:15 a.m. de cada día
15 20 * * * A las 8:15 p.m. de cada día
00 5 * * 0 A las 5 a.m. todos los domingos
* 5 * * Sun Cada minuto de 5:00a.m. a 5:59a.m. todos los domingos
45 19 1 * * A las 7:45 p.m. del primero de cada mes
01 * 20 7 * Al minuto 1 de cada hora del 20 de julio
10 1 * 12 1 A la 1:10 a.m. todos los lunes de diciembre
00 12 16 * Wed Al mediodía de los días 16 de cada mes y también todos los miércoles
30 9 20 7 4 A las 9:30 a.m. del día 20 de julio y también todos los jueves de julio
30 9 20 7 * A las 9:30 a.m. del día 20 de julio sin importar el día de la semana
20 * * * 6 Al minuto 20 de cada hora de los sábados
20 * * 1 6 Al minuto 20 de cada hora de los sábados de enero
Advertencia
Cuando se especifican a la vez el día del mes y el día de la semana (ninguno de los dos es *), cron ejecuta la tarea cuando se cumple uno u otro (unión), no los dos a la vez. Por eso 00 12 16 * Wed se ejecuta los días 16 y además todos los miércoles.
Ejemplo que se ejecute cada minuto:
crontab -l
* * * * * /root/encendido.sh
El programa cron se invoca cada minuto y ejecuta las tareas que sus campos se cumplan en ese preciso minuto.
Ejemplo de la utilización de rsync para hacer copias de seguridad
rsync -av --delete /home/dani /media/dani/Backup/
rsync -av --delete -e 'ssh -p22' dani@IP:/home/dani/ /media/dani/Backup/
Systemd#
Antiguamente se utilizaba el proceso init, este es el proceso “padre”, es el primer proceso que se ejecuta al iniciar el sistema(es lanzado directamente por el kernel), y se encarga de lanzar todos los demás procesos.
El demonio init tradicional es estrictamente síncrono: bloquea las tareas siguientes hasta que la actual se haya completado, y sus tareas deben definirse por adelantado y solo se ejecutan cuando init cambia de estado (cuando la máquina se arranca o se apaga). Para superar estas limitaciones Ubuntu lo sustituyó primero por Upstart y, desde Ubuntu 15.04, por Systemd, que es lo que usan hoy prácticamente todas las distribuciones.
Systemd está hecho para proveer un mejor framework para expresar las dependencias del servicio, permite hacer más trabajo paralelamente al inicio del sistema y reducir la sobrecarga del shell. El nombre viene del sufijo system daemon (procesos en segundo plano) con la letra “d”. Lo podemos comprobar:
$ ls /sbin/init -l
lrwxrwxrwx 1 root root 20 sep 17 10:35 /sbin/init -> /lib/systemd/systemd
Systemd reemplaza a la secuencia de arranque de Linux y los niveles de ejecución controlados por el demonio de inicio tradicional , junto con la ejecución de los scripts bajo su control.
En systemd el primer demonio de ejecución se llama precisamente systemd y es el que tiene PID 1.
En systemd los servicios se denominan units. Cada unit se define en un archivo donde se especifica un proceso para arrancar por systemd. Evidentemente el arranque de un unit puede estar supeditado a determinadas circunstancias como la dependencia de otros units.
Existen varios tipos de units, no sólo servicios, cuyos archivos se nombran con la extensión correspondiente:
servicios (.service)
puntos de montaje (.mount)
dispositivos (.device)
sockets (.socket)
Los archivos que definen los units (y los targets) se pueden encontrar básicamente en tres ubicaciones distintas:
/usr/lib/systemd/system/: unidades distribuidas con los paquetes instalados (en Debian/Ubuntu, /lib/systemd/system/).
/run/systemd/system/: unidades creadas en tiempo de ejecución. Tiene precedencia sobre el directorio anterior.
/etc/systemd/system/: unidades creadas y administradas por el administrador del sistema. Este directorio tiene precedencia sobre el directorio anterior.
El formato de un archivo unit sigue unas reglas y nomenclatura específicas. Básicamente se divide en varias secciones se las cuales las principales son:
[Unit]
[Service]
[Install]
A continuación se indican esquemáticamente las opciones más importantes dentro de cada sección.
[Unit]#
Description=<descripción del unit>
Una descripción del servicio que se muestra al consultar el status del servicio.
After=<units>
Define el orden en el cual los units se inician. El unit se inicia sólo después de que los units especificados en esta línea estén activos. La diferencia con Require es que After no activa explícitamente los units indicados aquí. La opción Before tiene la funcionalidad opuesta a After.
Requires=<units>
Configuras las dependencias sobre otras units. Los units listados aquí serán activados junto con este unit. Si alguno de los units requeridos falla en el arranque, este unit tampoco se activa.
Wants=<units>
Activa los units indicados aquí. Wants configura dependencias de manera más débil que Require. Si alguno de los units indicados por Wants no se inician correctamente no tienen ningún efecto en el estado de este unit. Wants es la manera recomendada para establecer dependencias personalizadas.
Conflicts=<units>
Configura dependencias negativas, es decir, es un opuesto a Requires. El servicio no se inicia si el servicio indicado en esta línea está activo.
[Service]#
TimeoutStartSec=<n>
Tiempo tras el cuál, si el servicio no ha arrancado, se considera fallo y se detiene.
ExecStart=<ejecutable>
comando a ejecutar.
Type=<opción>
Configura el tipo de arranque del procesos de la unidad la cual afecta a la funcionalidad ExecStart. Las opciones son:
simple – Es el valor por defecto. El proceso arrancado con ExecStart es el proceso principal del servicio. Este proceso se arranca inmediatamente. El proceso no debe desencadenar otros procesos que requieran ejecución en el algún orden. No utilizar este tipo si otros servicios necesitan ejecutarse en orden con él.
forking – El proceso iniciado con ExecStart genera un proceso hijo que se convierte en el proceso principal del servicio. Se sale del proceso padre cuando el arranque se completa. El uso de esta opción es importante cuando ejecutamos un script que a su vez ejecuta otros procesos. Sin la opción forking estos subprocesos podrían salir inesperadamente al concluir el proceso principal.
oneshot – Similar a simple, pero se sale del proceso antes de que se arranquen los subsiguientes units. Es útil para la ejecución de scripts que hacen un trabajo sencillo y luego salen. Con la opción RemainAfterExit=yes systemd considerará su proceso como activo después de que el proceso haya salido.
dbus – Similar a simple, pero los subsiguientes units sólo son arrancados después de que el proceso principal adquiera un nombre D-Bus.
notify – Similar a simple, pero los subsiguientes units sólo son arrancados después de que un mensaje de notificación se haya enviado mediante una función sd_notify().
idle – Similar a simple, la ejecución actual del binario del servicio se retrasa hasta que todos los trabajos se terminan, lo que evita la mezcla de la salida de estados con las salidas de los servicios por la Shell.
[Install]#
WantedBy=multi-user.target
Indica el target al que pertenece este unit. Esto provoca que el comando systemctl enable <servicio>.service cree los enlaces simbólicos necesarios dentro del target multi-user.target.wants sin necesidad de hacerlo manualmente.
Lo que se consigue con esto es que el servicio se ejecute automáticamente al arrancar ese target.
Los Targets#
Un conjunto de units definen un target. El target es el equivalente al concepto de runlevel, es decir, un conjunto de servicios que se ejecutan en determinadas circunstancias. Los runlevels clásicos de System V y su target equivalente son:
0 Apagado del sistema → poweroff.target
1 Monousuario (mantenimiento) → rescue.target
2, 4 Modo definido por el usuario/sistema, por defecto idéntico al 3
3 Multiusuario, sin entorno gráfico → multi-user.target
5 Multiusuario con entorno gráfico (todos los servicios del nivel 3 más el gráfico) → graphical.target
6 Reinicio → reboot.target
A diferencia de los runlevels, los targets se pueden ejecutar a la vez. Comandos útiles:
systemctl get-default # target con el que arranca el sistema
sudo systemctl set-default multi-user.target
sudo systemctl isolate graphical.target # cambiar de target en caliente
Systemctl#
En Systemd la forma de controlar los servicios del sistema cambia. Los servicios ya no se controlan a través de /etc/init.d y tampoco se utiliza el comando “service”. Aquí se utiliza el gestor de servicios llamado systemctl.
La principal orden para controlar systemd es systemctl. systemctl sustituye a chkconfig de System V.
systemctl es una herramienta potente con muchas opciones. A continuación se listan los más importantes atendiendo su funcionalidad.
systemctl #Lista servicios y unidades disponibles en el sistema.
systemctl list-unit-files #Lista ficheros de unidades
systemctl list-units #Lista las unidades cargadas
systemctl list-dependencies <servicio> #Lista las dependencias de un servicio
systemctl show <service> # Visualizar las propiedades del unit.
systemctl start <servicio> # Arrancar servicios.
systemctl stop <servicio> # Parar servicios.
systemctl status <service> # Visualiza el estado e información de un servicio.
systemctl is-active <service> # Muestra simplemente si el servicio está activo
systemctl enable <servicio> # Habilita un servicio en el arranque.
systemctl disable <servicio> # Deshabilita un servicio en el arranque.
systemctl restart <servicio> # Reinicia un servicio.
systemctl reload <servicio> # Recarga la configuración de un servicio sin reiniciarlo
systemctl mask <servicio> # Marca un servicio como completamente inarrancable
Ejemplo :
$ service --status-all | grep ssh
[ + ] ssh
$ systemctl stop ssh
$ service --status-all | grep ssh
[ - ] ssh
$ systemctl start ssh
$ service --status-all | grep ssh
[ + ] ssh
Ejemplo de encadenamiento de servicios#
Servicio A personalizado se ejecuta automáticamente en el arranque con el target multi-user.target:
[Unit]
Description=Servicio A
Requires=multi-user.target
[Service]
Type=simple
ExecStart=/bin/servicioA.sh
[Install]
WantedBy=multi-user.target
Servicio A se ejecuta automáticamente con el arranque en el target multi-user.target. El servicio A una vez iniciado, lanza al servicio B:
[Unit]
Description=Servicio A
Requires=multi-user.target
Wants=ServicioB.service
[Service]
Type=simple
ExecStart=/bin/servicioA.sh
[Install]
WantedBy=multi-user.target
servicio B
[Unit]
Description=Servicio B
[Service]
Type=simple
ExecStart=/bin/servicioB.sh
[Install]
Servicio A se ejecuta automáticamente con el arranque en el target multi-user.target. Una vez iniciado el servicio A, éste lanza al servicio B cuando el servicio A concluye:
[Unit]
Description=Servicio A
Requires=multi-user.target
[Service]
Type=simple
ExecStart=/bin/servicioA.sh
ExecStop=/usr/bin/systemctl start ServicioB.service
[Install]
WantedBy=multi-user.target
servicio B
[Unit]
Description=Servicio B
[Service]
Type=simple
ExecStart=/bin/servicioB.sh
[Install]
Acceder a los registros del sistema#
La forma básica de acceder a los registros del sistema es:
journalctl # cat /var/log/messages
journalctl -f # tail -f /var/log/messages
journalctl --list-boots # Filtrar la salida de logs por boots
journalctl -b # Logs del boot actual
journalctl -b -1 # Anteriores
journalctl -k # Ver los mensajes del kernel
journalctl -n # Filtrar por número de entradas
journalctl _COMM=NetworkManager # Filtras por ejecutables o programas
journalctl /usr/sbin/NetworkManager # Filtrar por especificando la ruta
journalctl _PID=2527 # Mostrar la salida por PID
journalctl _UID=1001 # id de los usuarios
journalctl --since '30 min ago' # Última media hora:
journalctl /dev/sda # Funcionamiento en nuestras unidades de discos duros
journalctl --disk-usage # Ver el espacio que están ocupando
systemctl list-units -t service --all # Filtrar la salida por servicios de systemd
journalctl -u dbus.service # Si nos interesa uno en particular
#Filtrar por intervalos de tiempo
journalctl --since 'yesterday' --until '02:00'
journalctl --since='2015-02-29 00:01' --until='2015-03-29 00:01'
#Filtrar por programas e intervalos
journalctl _COMM=firefox --since='2015-02-29 00:01' --until='2015-03-29 00:01'
journalctl -u sshd.service --since='2015-02-29 00:01' --until='2015-03-29 00:01'
Ejemplo de servicio encendido#
$ cat /root/encendido.sh
#!/bin/bash
date >> /root/encendido.log
Para que se inicie automáticamente utilizamos el sistema systemctl
$ cat /etc/systemd/system/encendido.service
[Unit]
Description=Inicia registro encendido
After=syslog.target
[Service]
ExecStart=/root/encendido.sh
User=root
[Install]
WantedBy=multi-user.target
$ chmod +x /root/encendido.sh
$ systemctl daemon-reload # recarga los archivos de unidades tras crear uno nuevo
$ systemctl enable encendido.service
$ systemctl start encendido.service
$ systemctl list-unit-files