lunes, 11 de junio de 2018

Programar tareas: CRON y CRONTAB

Nunca me ha preocupado excesivamente este tema de hacer que el PC ejecute, de forma programada, alguna tarea específica… pero mira por donde, hablando estos días del tema de hacer un backup de mi /home, se me ocurrió que podría tener algún interés aprender a hacerlo… y aquí estoy, para aclarar (y aclararme) algunos conceptos.

La idea central es, por tanto, poder crear una orden (por ejemplo, un script) para hacer que el ordenador la ejecute en la fecha y hora que le indiques. Sencillo ¿no?

Bien, pues para eso, tradicionalmente, Linux siempre ha puesto a disposición del usuario dos herramientas que se llaman ‘cron’ y ‘crontab’. Vamos a echarles un vistazo...
Por centrar conceptos:
CRONTAB no es más que el fichero de texto, donde se deben indicar esos procesos y tareas a ejecutar, y su pauta temporal prevista. Este fichero se guarda en la ruta /var/spool/cron/crontabs/. También, con ese mismo nombre, es un comando, cuyo 'man crontab' se puede consultar.

Y CRON es otro comando, un 'demonio', que se instala por defecto, y que, ejecutándose en segundo plano, revisa cada minuto las ‘tareas crontab’ definidas y ordena, si es el caso, que se ejecuten.
Leo, sin embargo, que con el famoso ‘systemd’, hay un proyecto de reemplazar el ‘cron’ por los ‘timers’. Espero que, si se lleva a cabo un reemplazo ‘absoluto’, sea muy tarde. Yo no me voy a meter en líos técnicos: el cron funciona, y esto que voy a decir aquí pienso que es todo lo que se necesita saber, si no eres un ‘friki’.
Una cuestión previa: habilitar el registro CRON
Una de las cosas que se recomiendan, si vas a programar tareas, es tener un ‘log’ de CRON. No cuesta mucho guardarlo, y siempre puede venir bien como ayuda para identificar errores o fallos. Para ello, como por defecto viene deshabilitado, habría que hacer esto: 
1- Ir al archivo /etc/rsyslog.conf, y editarlo, como root 
sudo nano /etc/rsyslog.conf 
2- Busca la linea… 
#cron.* /var/log/cron.log 
3- Descomentarla, para que quede asi: 
cron.* /var/log/cron.log 
4- Hecho esto, guardar los cambios y cerrar el editor. Y solo queda reiniciar el servicio “rsyslog“ con 
sudo systemctl restart rsyslog 
Y, de forma automática, se creará el archivo “cron.log” en la carpeta “/var/log”. 

Como programar una tarea, con CRON
Es muy sencillo: Basta escribir, en una consola
crontab -e 
(nota, si hay varios usuarios, creo que la orden es ‘crontab -e -u nombre_usuario’)
La primera vez que lo hagas te dirá que no hay ningun crontab, y que uses uno nuevo (vacío). Y te preguntará con qué editor de texto quieres trabajar. 
Eliges nano, que es muy sencillo de usar. Y te aparece el editor con un montón de líneas explicativas y ejemplos, todas ‘comentadas’ (con una ‘#’ inicial). 
Las siguientes veces que escribas ‘crontab -e’ ya pasas, directamente, a aquí. 
Bien pues al final del archivo te aparece esta línea, que es la importante:
# m h dom mon dow command 
de la que enseguida me ocuparé, porque es la guía para definir la pauta temporal (cuando quieres que se ejecute la tarea) y el comando que la lanza (una orden directa, un script…), que se irían poniendo (por supuesto, sin 'comentar') a continuación.

Y una cuestión importante: cuando lanzas crontab -e (como usuario) tienes que poner la ruta absoluta del comando. En mi caso, como los scripts los suelo guardar en la raiz de mi /home, esta ruta (y el comando para ejecutar un script) sería...
/home/doc/sh nombre_script

Y ya está. Se pueden poner, línea a línea, cuantas tareas quieras. Cada una ejecutará el comando que indique, ‘cuando toque’ (en la pauta temporal añadida).
Y, por supuesto, cuando quieras que deje de ejecutarse una orden programada, te basta abrir una terminal, editar 
crontab -e 
y o bien borrar, o bien ‘comentar’ (con ‘#’ previa) la línea que contenga la orden a anular. 

Las pautas temporales
Esos campos ‘m h dom mon dow ...’ que indicaba sirven para definir las pautas temporales. Es muy sencillo, significan minuto, hora, día (del mes) mes y día de la semana. Esta imagen lo explica muy bien

así que, teniendo en cuenta que * significa ‘todos’ (o ‘cualquiera’) con unos cuantos ejemplos quedará muy claro: 
01 * * * *     Significa que se debe ejecutar en el minuto 1 de cada hora de todos los días 
15 8 * * *     Significa que se ejecutará a las 8:15 de la mañana de cada día 
15 20 * * *   A las 8:15 de la tarde (o sea, las 20:15 horas) de cada día 
15 20 * * 0   A las 8:15 de la tarde, de todos los domingos del año 
30 9 20 7 4   A las 9:30 de la mañana del 20 de julio, siempre que sea jueves (lo cual puede ser difícil, claro)
30 9 20 7 *   A las 9:30 de la mañana del 20 de julio, sin importar el día de la semana 
* 5 * * 0       Cada minuto, de 5:00 a.m. a 5:59 a.m., todos los domingos 
45 19 1 * *   A las 7:45 de la tarde 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 
20 * * * 6    Al minuto 20 de cada hora de todos los sábados 
20 * * 1 6    Al minuto 20 de cada hora de los sábados de enero 
Hay también algunas anotaciones especiales. Por ejemplo… 
hacer algo de lunes a viernes… 1,2,3,4,5 (o 1-5) 
hacer algo ‘cada 5 horas, en el minuto 0’ se pondría así: 0 */5 (etc) 
o bien ‘todos los días, cada 15 minutos, de 10 a 14:00 horas’… */15 10-14 * * * 
(bueno, y etc, siempre existe Google para consultar algún manual de CRON) 

Un ejemplo práctico
Decía yo, al final de esta entrada que aunque GrSync no admite poder programar un backup automático, cada cierto tiempo, siempre podría programarlo con CRON y CRONTAB, y solucionado. Y es bien sencillo: si esta copia de seguridad la hiciese en una partición montada automáticamente, bastaría poner como comando 'grsync'

Pero, en mi caso, como la copia la voy a hacer en un disco duro externo, que normalmente estará desconectado, me valgo de este pequeño truco: que (acordándome de que, hace unos meses, aprendí cosas sobre el 'scripting', con Zenity), se ejecute este aviso:

Y esto lo hago con este simple script (que llamaré backupHome.sh)
#!/bin/bash
zenity --info \
--width="300" --height="200" --text="TE TOCA HACER UN BACKUP DE TU HOME
1º - Enchufa el disco externo
2º - Vete a Menu-Administración-GSync
3º - Activa la sesión Backup_Home"
y con este recordatorio, que, por ejemplo, planifico para que me aparezca a las 16.00 horas de todos los lunes, con la orden
0  16  *  *  1 /home/doc/backupHome.sh
que añado a mi crontab, editándolo con
crontab -e
y copiando y pegando esa línea al final del archivo
soluciono lo de mis backups periódicos... si hago caso al aviso que me saltará todos los lunes, a las 16:00 horas.

NOTA MUY IMPORTANTE 
Como, para mi,  todo esto es 'pura teoría' que practico por primera vez, me puse a probar... y descubrí que esto del crontab no funcionaba, que no se lanzaba el script indicado. Tras revisar sintaxis, etc, descubro que hay bastante info, en Google, donde se habla del NO funcionamiento de crontab -e. 
Y muchas soluciones... que tampoco me resolvieron el problema. 
Por ejemplo, veo que en el log de CRON me aparece el mensaje 'No MTA installed, discarding output' (MTA (Mail Transfer Agent) es un servidor de correo que, al parecer, necesita CRON). Instalo, según se recomienda, postfix, que hace desaparecer el mensaje... pero sigue sin lanzarse el script.
Por supuesto, también marco en el script el permiso de ejecutarse como programa, y los de acceso y escritura
chmod a+x script 
y nada, sigue sin aparecer la ventana de información del script. 
Pero, muy a final, conseguí la solución leyendo en un foro ¡de 2008...! que se podía probar poner la orden, en crontab -e, así:
0 16 * * 1 export DISPLAY=:0 && gnome-terminal --command="sh /home/doc/backupHome.sh"

¡¡¡Y ME FUNCIONÓ...!!! 

(Y NOTA FINAL, para los estudiosos: leo también que si el ordenador está apagado cuando toque ejecutar una tarea, CRON y CRONTAB sencillamente se la saltan a la torera. Por eso se usan mucho en servidores, que suelen estar encendidos siempre. Pero para portátiles y sobremesas de uso esporádico, es mejor programar las tareas con ANACRON, que tiene la ventaja de que, si el PC está apagado cuando toca ejecutar una tarea programada, ésta de ejecuta en el siguiente arranque)
(Y digo que esto es 'para estudiosos' porque no me apetece nada ponerme a estudiar, ahora, el ANACRON) 

PERO... ¡DESENLACE FINAL...!
Qué gran verdad contiene el famoso principio de 'la navaja de Ockham'...! Si hombre, eso de que no hay que olvidarse nunca de que 'la solución más sencilla es, muy a menudo, la más adecuada'...
Y es que, repasando el tema, porque había reinstalado mi Debian y tenía que reactivar el aviso de hacer un backup, se me ocurrió una chorrada muy simple, que era lo de otro dicho famoso: 'el huevo de Colón'.
Vamos, que lo solucioné creandome una imagen con el texto 'Acuérdate de hacer Backup con GrSync' y poniéndola, bien a la vista, en el escritorio. Y así, siempre que arranco, o paso por la 'vista Escritorio', veo el recordatorio, y decido. 


Y no hacen falta todas estas historias del cron, el anacron, el script_backupHome, etc., etc.  Bueno, seamos justos, por lo menos han servido para aprender alguna cosa más... y para dejar anotado en el Blog el 'apunte táctico'.

No hay comentarios:

Publicar un comentario