Quiero ejecutar un script de shell literalmente cada 3 días. El uso de crontab con 01 00 */3 * *
no cumplirá la condición, ya que se ejecutará el 31 y luego nuevamente el primer día de un mes. La */3
sintaxis es la misma que decir 1,4,7 ... 25,28,31.
Debería haber formas de hacer que el script compruebe las condiciones y salga si no han pasado 3 días. Entonces crontab ejecuta el script todos los días, pero el script en sí mismo verificará si han pasado 3 días.
Incluso encontré algo de código, pero me dio un error de sintaxis, cualquier ayuda sería apreciada.
if (! (date("z") % 3)) {
exit;
}
main.sh: line 1: syntax error near unexpected token `"z"'
main.sh: line 1: `if (! (date("z") % 3)) {'
command-line
bash
scripts
cron
Taavi
fuente
fuente
*/3
no funciona? "si no han pasado 3 días": ¿tres días desde qué? Por favor, editar su pregunta y aclarar.date("z") % 3 == 0
sufriría un problema similar: la condición será falsa durante los cuatro días entre el 29 de diciembre y el 3 de enero, a menos que ese diciembre sea parte de un año bisiesto.Respuestas:
Para abortar inmediatamente y salir de un script si la última ejecución aún no fue al menos hace un tiempo específico, puede usar este método que requiere un archivo externo que almacene la última fecha y hora de ejecución.
Agregue estas líneas a la parte superior de su script Bash:
No olvide establecer un valor significativo como
datefile=
y adaptar el valorseconds=
a sus necesidades (se$((60*60*24*3))
evalúa en 3 días).Si no desea un archivo separado, también puede almacenar el último tiempo de ejecución en la marca de tiempo de modificación de su script. Sin embargo, eso significa que al hacer cualquier cambio en su archivo de script se restablecerá el contador 3 y se tratará como si el script se estuviera ejecutando correctamente.
Para implementar eso, agregue el fragmento a continuación en la parte superior de su archivo de script:
Nuevamente, no olvide adaptar el valor de
seconds=
sus necesidades (se$((60*60*24*3))
evalúa en 3 días).fuente
$[ $(date +%s) - $(< lastrun) ]
. Si el script se ejecuta desde cron una vez al día, podría agregar algo de holgura al intervalo de tiempo requerido, de modo que si la ejecución del script se retrasa un par de segundos, la próxima vez no se saltará un día completo. Eso es comprobar todos los días si han pasado 71 horas.Cron realmente es la herramienta incorrecta para esto. En realidad, existe una herramienta comúnmente utilizada y poco querida llamada en la que podría funcionar. at está diseñado principalmente para uso interactivo y estoy seguro de que alguien encontrará una mejor manera de hacerlo.
En mi caso, tendría el script que estoy ejecutando en testjobs.txt, e incluiría una línea que lea.
Como ejemplo, tendría esto como testjobs.txt
Tengo dos comandos inocentes, que podrían ser sus shellscripts. Ejecuto echo para asegurarme de que tengo una salida determinista y la fecha para confirmar que el comando se ejecuta según sea necesario. Cuando ejecuta este comando, terminará agregando un nuevo trabajo a durante 3 días. (Lo probé con un minuto, lo que funciona)
Estoy bastante seguro de que se me llamará por la forma en que he abusado, pero es una herramienta útil para programar un comando para que se ejecute en un momento o x días después de un comando anterior.
fuente
at
parece el mejor enfoque aquí. El problema con este enfoque es que cada vez que ejecutas manualmente el script, agregas otro conjunto deat
tareas cada 3 días .at
está en la parte superior, o potencialmente mucho más siat
está cerca de la parte inferior de un script de ejecución larga)Primero, el fragmento de código anterior es una sintaxis Bash no válida, se parece a Perl. En segundo lugar, el
z
parámetro adate
hace que genere la zona horaria numérica.+%j
Es el número del día. Necesitas:Pero todavía verás extrañeza al final del año:
Es posible que tenga más suerte manteniendo un conteo en un archivo y probando / actualizando eso.
fuente
date()
función incorporada, pero se parece un poco a date () en PHP (dondez
es "El día del año (a partir de 0)")Si puede dejar el script ejecutándose perpetuamente, puede hacer lo siguiente:
Este bucle siempre es verdadero, por lo que siempre ejecutará el código, luego esperará tres días antes de comenzar el bucle nuevamente.
fuente
while true
?at
solución, esto dependerá del tiempo de ejecución del script en cada ejecución. Por supuesto, eso se puede solucionar ahorrando el tiempo cuando comienza el script y durmiendo hasta 3 días después de eso.Puede usar anacron en lugar de cron, está diseñado exactamente para hacer lo que necesita. Desde la página del manual:
fuente