Necesito comenzar un cronjob todos los días, pero una hora más tarde cada día. Lo que tengo hasta ahora funciona en su mayor parte, excepto por 1 día del año:
0 0 * * * sleep $((3600 * (10#$(date +\%j) \% 24))) && /usr/local/bin/myprog
Cuando el día del año es 365, el trabajo comenzará a las 5:00, pero el día siguiente (sin contar un año bisiesto) tendrá un día del año como 1, por lo que el trabajo comenzará a la 1:00. ¿Cómo puedo deshacerme de este caso de esquina?
Respuestas:
Mi solución preferida sería comenzar el trabajo cada hora, pero hacer que el script compruebe si es hora de ejecutarlo o no y salir sin hacer nada 24 de 25 veces.
crontab:
en la parte superior de
myprog
:Si no desea realizar ningún cambio en el script en sí, también puede poner la comprobación de "tiempo de ejecución" en la entrada de crontab, pero crea una línea larga y desagradable:
fuente
date
regresó del kernel fue1ms
anterior al tiempo que esperaba que se ejecutara el script, la verificación daría un resultado incorrecto.ntpd
, se esfuerza por solo girar el reloj, no saltarlo, específicamente para evitar este tipo de problema, pero tienes razón, (ontpdate
) a veces puede saltar el tiempo hacia atrás. En cuanto acron
calcular mal su retraso de sueño, ¡estoy bastante seguro de que se consideraría un error! Aún así, punto tomado, y una solución alternativa sería programar el trabajo 30 minutos después de la hora, lo que es menos probable que cause el problema ... O agregue ± 1800 en la expresión aritmética antes de tomar el mod mod 3600.Si su sistema tiene systemd, puede usar temporizadores para esto. Simplemente defina un nuevo servicio , que debe contener el comando / tarea que desea ejecutar, y luego cree un evento de temporizador con la
OnUnitActiveSec
opción:Use el mismo nombre para los archivos, excepto que en lugar de
.service
usarlos.timer
.Sintetizando:
job.service
en el/etc/systemd/system/
directorio.systemctl status job.service
.job.timer
en/etc/systemd/system/
.Rellene con la información requerida:
systemctl list-timers
fuente
Si no le importa usar algo que no sea cronjobs, sugeriría la utilidad menos conocida
at
. Simplemente escriba un script de envoltura que se programe para ejecutarse en 25 horas, y luego llame a su programa. Esta parece ser la solución más limpia.Por ejemplo, podría escribir esto en ~ / script.sh:
Y luego simplemente corre
bash ~/script.sh
una vez.Gracias a @HalosGhost por la idea de programar el trabajo una vez cada 25 horas.
fuente
at
para este propósito: (1) si el trabajo no se ejecuta correctamente incluso una vez, probablemente también no se reprograme y luego no solo la próxima ejecución sino que todas las ejecuciones futuras se cancelen efectivamente hasta que un humano se dé cuenta, y (2) dado que el trabajo tarda un tiempo distinto de cero en ejecutarse, el uso ingenuonow + 25 hours
significa que se ejecutará unos segundos (o más) más tarde cada vez, y si este retraso se acumula con el tiempo, eventualmente se ejecutará completamente en el mal hora.at
se limita a minutos y comienza todos los trabajos a las [hora]: 00.at
trabajo a primera hora en el script at evita esos problemas. No obstante, si se produce un error, se rompe toda la cadena, lo que puede o no ser deseado: si el caso de uso es "solo ejecutar esto cuando funciona", no reiniciar es una gran característica. Pero si el caso de uso "siempre se ejecuta, incluso si falla el último", entoncesat
no es la herramienta correcta.