cron · programación de tareas · unix
¿Qué es cron, exactamente?
Una entrada cron son cinco campos de tiempo y un comando. En orden: minuto, hora, día del mes, mes, día de la semana.
30 4 * * 1 /usr/local/bin/backup.sh Se lee: minuto 30, hora 4, cualquier día del mes, cualquier mes, día de la semana 1. Las cuatro y media de la madrugada, los lunes.
El vocabulario de un campo
Cada campo admite más que un número suelto. * significa todos los valores. 1-5 es un rango. 1,15 es una lista. */15 es un paso: un valor de cada quince, o sea cuatro veces por hora en el campo de los minutos.
Dos campos admiten además nombres: los meses de JAN a DEC, los días de la semana de SUN a SAT. Y el campo del día de la semana tiene una rareza conocida: tanto 0 como 7 significan domingo en la mayoría de implementaciones.
El campo que es un O
Aquí está la parte que sorprende, y merece una segunda lectura.
El día del mes y el día de la semana son dos formas distintas de nombrar el mismo día. Si rellenas solo uno y dejas el otro en *, cron se comporta como esperas. Si rellenas los dos, POSIX especifica que un día que coincida con cualquiera de los campos dispara la tarea.
Es un O, no un Y.
Así que 0 0 1 * 1 no significa «el primero del mes, si cae en lunes». Significa el primero de cada mes, y todos los lunes, es decir unas cinco veces más ejecuciones de las previstas.
El razonamiento detrás de la decisión se sostiene. Un Y haría que casi ninguna combinación se disparara: «el 31 cuando sea viernes» ocurre una o dos veces al año. El O permite que una sola línea exprese «mensual y semanal» sin una segunda entrada. Pero es lo contrario de lo que la sintaxis aparenta, y ahí es donde las tareas programadas se ejecutan sin ruido los días equivocados.
Los atajos, y por qué no son portables
Muchas implementaciones aceptan @daily, @hourly, @weekly, @monthly y @reboot. Son cómodos y no forman parte de POSIX: vienen de Vixie cron y sus descendientes.
En una máquina que controlas, da igual. En algo que debe funcionar en cualquier sitio - una imagen de contenedor, un script que distribuyes - los cinco campos explícitos son la opción segura. @reboot en particular no tiene equivalente alguno en el estándar, y su comportamiento depende por completo de la implementación.
Lo que cron no hace
No recupera lo perdido. Si la máquina estaba apagada a las 4:30, la tarea de las 4:30 no se ejecutó y no se relanzará. Cron dispara por coincidencia de reloj, no mantiene una cola de trabajo pendiente.
No te da tu entorno de sesión. Una tarea cron se ejecuta con un PATH mínimo y sin nada de tu perfil de shell. El «funciona en mi terminal pero no en cron» más común es un comando encontrado por un PATH que cron no tiene. Usa rutas absolutas.
No evita el solapamiento. Si una tarea programada cada cinco minutos tarda seis, acabas con dos copias a la vez. Cron lanzará la siguiente igualmente; el fichero de bloqueo es cosa tuya, no suya.
No te avisa de que falló. La salida va al correo si el correo está configurado, y a ninguna parte si no lo está. Redirige a un fichero de registro y míralo, o te enterarás por la copia de seguridad que falta.
Lee la expresión antes de fiarte de ella
Como el O es invisible en la sintaxis, una expresión que parece correcta puede estar mal de un modo que solo se nota semanas después. Descodificarla campo por campo antes de desplegar cuesta unos segundos: para eso está el descodificador de expresiones cron de este sitio.
Un calendario con los nombres de los días al lado y los números en la cuadrícula. Cron tiene un campo para cada uno, y cuando rellenas ambos, coincide con uno U otro, no con los dos juntos.