Ejecutar programas por horario en Linux (ejemplo con Raspberry Pi)

Introducción
Muchos sistemas operativos Linux incluyen el servicio crontab, el cual es extremadamente útil para ejecutar programas ya sea en una fecha específica, o con alguna periocidad. La resolución máxima de crontab es de un minuto y la mínima es de una vez al año.

Para usar crontab se debe editar el archivo de configuración, para eso, es necesario escribir en la consola:
crontab -e
. Una vez escrito el comando, se debe escojer el editor de texto que se desea utilizar para editar el archivo de configuración. El archivo de configuración es pequeño y simple, por lo que se recomienda utilizar la opción nano. Deberías ver algo similar a esto:

archivo de configuración de crontab utilizando nano En nano, para guardar y salir, debes apretar "ctrl+x", luego "y" y finalmente Enter.
La periocidad se define en crontab con el siguiente formato:
m h dom mon dow commando
Donde las variables son (de izquierda a derecha):
  • m: minuto. toma valores 0-59
  • h: hora. toma valores 0-23
  • dom: día del mes. toma valores 1-31.
  • mon: mes. toma valores 1-12 (o nombres)
  • dow: dia de la semana. toma valores 0-7 (0 y 7 es Domingo).
  • commando: el comando que deseas ejecutar en el horario establecido.
Por ejemplo, para correr un script de python llamado correr.py el jueves 30 de mayo a las 23:17 horas:
#todos los jueves 30 de mayo a las 23:17
17 23 30 5 4 /usr/bin/python /home/lab/correr.py
Notemos lo siguiente:
  • Es necesario utilizar rutas absolutas, incluso en el script correr.py.
  • El script va a correr todos los años que sea jueves el 30 de mayo (2019, 2024, 2030, etc)
Podemos hacer que el script corra todos los 30 de mayo a las 23:17, si hacemos:
#todos los 30 de mayo a las 23:17
17 23 30 5 1,2,3,4,5,6,7 /usr/bin/python /home/lab/correr.py
Podemos escribir un rango, del 1 al 7 haciendo:
#todos los 30 de mayo a las 23:17
17 23 30 5 1-7 /usr/bin/python /home/lab/correr.py
Podemos reemplazar "todos los valores", por un asterísco "*", por lo tanto, equivalentemente podemos escribir:
#todos los 30 de mayo a las 23:17
17 23 30 5 * /usr/bin/python /home/lab/correr.py
Podemos hacer que este código corra todos los 30 de mayo cada 15 minutos:
#todos los 30 de mayo cada 15 minutos
*/15 * 30 5 * /usr/bin/python /home/lab/correr.py
Podemos hacer que este código corra todos los 30 de mayo y 5 al 15 de mayo cada 15 minutos:
#todos los 30 de mayo y 5 al 15 de mayo cada 15 minutos
*/15 * 30,5-15 5 * /usr/bin/python /home/lab/correr.py
Podemos agregarle mucha más complejidad, por ejemplo:
#cada 15 minutos y en el minuto 10 de las horas 00 y 12, del 1 al 15 de mayo más los días pares, de los meses mayo a diciembre solo si es lunes, miercoles o jueves.
*/15,10 */12 1-15,*/2 5-12 1,3-4 /usr/bin/python /home/lab/correr.py
Típicamente no se hacen configuraciones tan complejas. Es muy común querer ejecutar un comando cada minuto:
#cada 1 minuto
* * * * * /usr/bin/python /home/lab/correr.py
O cada 10 minutos:
#cada 10 minutos
*/10 * * * * /usr/bin/python /home/lab/correr.py
Una vez al día a las 12:00:
#Una vez al día a las 12:00
0 12 * * * /usr/bin/python /home/lab/correr.py
Consideraciones importantes de crontab:
  • Es necesario utilizar rutas absolutas, incluso en el script correr.py.
  • cron requires that each entry in a crontab end in a newline character. Es decir, no olvidar dejar un espacio en blanco al final del crontab.
  • Puedes instalar un crontab como superuser haciendo sudo crontab -e
  • Asegurate que el comando corre si lo ejecutas desde la consola, en este ejemplo: /usr/bin/python /home/lab/correr.py. Debuggear en crontab es dificil.
  • A veces un código podría no correr igual cuando lo ejecutas desde la consola, esto podría deberse a que la variable $PATH, no está seteada correctamente en el crontab.
Para setear la variable $PATH en el crontab, hacer en una terminal:
echo $PATH
Luego copiar el string de la siguiente manera al comienzo del crontab (utiliza el string que te salió a ti):
export PATH=$PATH:/home/lab/bin:/home/lab/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin