lunes, 6 de octubre de 2014

Programar eventos en Linux con CRON

Linux (y otros sistemas operativos basados en UNIX) posee una poderosa herramienta que permite programar eventos. Gracias a ello, podremos configurar que, cada cierto tiempo, se lance algún comando o programa. Esto es realmente útil, para tareas periódicas, tales como backups o copias de seguridad, transferencia de datos de un sistema a otro, copia de ficheros entre programas, etc.

CRON es un administrador de procesos en segundo plano (o demonios), y se encarga de revisar, a cada minuto, la lista de tareas o procesos programados en el fichero crontab, el cual está ubicado en /etc/crontab. Dentro de este fichero podemos configurar el intervalo en el que se ejecutarán las tareas, automatizando éstas. Cuando CRON revisa crontab, comprueba si hay alguna tarea o proceso que ejecutar en ese momento.

Para editar el crontab, ejecutar el siguiente comando:

sudo crontab -e

Con esto, se abrirá el editor para modificar el crontab correspondiente al usuario actual.

Las líneas de este fichero tienen el siguiente formato:

m h dom mon dow [usuario] comando

donde:

  • m: (minute) Minuto (0 a 59)
  • h: (hour) Hora (0 a 23)
  • dom: (day of month) Día del mes (1 a 31)
  • mon: (month) Mes (1 a 12)
  • dow: (day of week) Día de la semana (0 (domingo) a 6 (sábado))
  • usuario: Nombre del usuario Unix que lanza la tarea
  • comando: Comando Unix que ejecuta la tarea

Los parámetros m, h, dom, mon y dow pueden tener valores especiales:

  • * : (asterisco) Cualquier valor
  • valor1[,valor2...] : (lista separada por comas) Cualquiera de los valores especificados en la lista

Ejemplos:

  • 30 * * * * root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) cada minuto 30, a todas horas, todos los días y todos los meses
  • 0 23 * * 1,3,5 echo "Se ha ejecutado":A las 23:00 horas los lunes(1), miércoles(3) y viernes(5)
  • 0 23 * * mon,wed,fri echo "Se ha ejecutado":A las 23:00 horas los lunes(mon), miércoles(wed) y viernes(fri)
  • 30 7 1 * * root /etc/backup/backup.sh:Lanza el script backup.sh a las 7:30 de día 1 de cada mes, cualquier día de la semana

Existen algunas plantillas que facilitan el uso de los parámetros de frecuencia:

  • @hourly root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) en el primer minuto de cada hora (0 * * * * ...)
  • @daily root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez al día, a las 00:00 horas (0 0 * * * ...)
  • @midnight root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez al día, a las 00:00 horas (0 0 * * * ...)
  • @weekly root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez a la semana (domingos, a las 00:00 horas) (0 0 * * 0 ...)
  • @monthly root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez al mes (día uno, a las 00:00 horas) (0 0 1 * * ...)
  • @yearly root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez a la año (día 1 de Enero, a las 00:00 horas) (0 0 1 1 * ...)
  • @annually root sudo apt-get update & sudo apt-get dist-upgrade:Actualiza el sistema (Debian, Ubuntu, Mint...) una vez a la año (día 1 de Enero, a las 00:00 horas) (0 0 1 1 * ...)

Otros parámetros de crontab:

  • crontab -l: Muestra las tareas CRON del usuario actual
  • crontab -r: Elimina el crontab

Para ver el log de CRON:

sudo nano /var/log/syslog

Puede ocurrir que en el log aparezca un error como éste:

CRON[8380]: (CRON) info (No MTA installed, discarding output)>/p>

Esto se debe a que CRON necesita tener configurado un servidor de correo para las notificaciones. Por ello, será necesario instalar postfix

sudo apt-get install postfix

Otra forma de evitar estos mensajes es cambiar la salida de las notificaciones, añadiendo al final de cada tarea en crontab lo siguiente:

[tarea] >/dev/null 2>&1