Ejecute un script a través de cron cada dos semanas

12

He investigado bastante sobre cómo hacer esto, y veo que no hay forma directa en cron de ejecutar un trabajo, digamos, cada dos jueves.

En este momento, me estoy inclinando hacia la creación de un script que se ejecutará todas las semanas, y tocará un archivo de "marca" cuando se ejecute, y si se ejecuta y el archivo ya está allí, para eliminar el archivo (y no realizar el acción quincenal).

Mi pregunta es, ¿hay alguna otra forma más elegante o más simple de lograr este objetivo de un script bash de acciones que se ejecutan cada dos semanas automáticamente?

¡Gracias!

dmkmills
fuente
1
En lugar de un archivo de marca, puede usar números de semana ISO. (Por ejemplo,% V del strftime)
@Roger: Supongo que te refieres a un condicional dentro del script.
Pausado hasta nuevo aviso.
@Dennis: No tiene que ser así (por ejemplo, vea cómo mi respuesta se comprueba fuera del script), pero mi punto principal es que sería mucho más simple y no requeriría ningún estado en el sistema de archivos. Sin embargo, me di cuenta de que tiene un inconveniente similar al día de verificación del mes: algunos años tienen 53 semanas y otros tienen 52.

Respuestas:

11
0 0 * * Thu bash -c '(($(date +\%s) / 86400 \% 14))' && your-script

Solía ​​bash para hacer mis cálculos porque soy vago; cambia eso a lo que quieras. Aprovecho que el 1 de enero de 1970 es jueves; para otros días de la semana, tendría que aplicar una compensación. Cron necesita que se escapen los signos de porcentaje.

Comprobación rápida:

function check {
  when=$(date --date="$1 $(($RANDOM % 24)):$(($RANDOM % 60))" --utc)
  echo -n "$when: "
  (($(date +%s --date="$when") / 86400 % 14)) && echo run || echo skip
}

for start in "2010-12-02" "2011-12-01"; do
  for x in $(seq 0 12); do
    check "$start + $(($x * 7)) days"
  done
  echo
done

Tenga en cuenta que he elegido momentos aleatorios para mostrar que esto funcionará si se ejecuta en cualquier momento el jueves, y elegí fechas que cruzan los límites del año más incluyen meses con 4 y 5 jueves.

Salida:

Thu Dec  2 06:19:00 UTC 2010: run
Thu Dec  9 23:04:00 UTC 2010: skip
Thu Dec 16 05:37:00 UTC 2010: run
Thu Dec 23 12:49:00 UTC 2010: skip
Thu Dec 30 03:59:00 UTC 2010: run
Thu Jan  6 11:29:00 UTC 2011: skip
Thu Jan 13 13:23:00 UTC 2011: run
Thu Jan 20 20:33:00 UTC 2011: skip
Thu Jan 27 16:48:00 UTC 2011: run
Thu Feb  3 17:43:00 UTC 2011: skip
Thu Feb 10 05:49:00 UTC 2011: run
Thu Feb 17 08:46:00 UTC 2011: skip
Thu Feb 24 06:50:00 UTC 2011: run

Thu Dec  1 21:40:00 UTC 2011: run
Thu Dec  8 23:24:00 UTC 2011: skip
Thu Dec 15 22:27:00 UTC 2011: run
Thu Dec 22 02:47:00 UTC 2011: skip
Thu Dec 29 12:44:00 UTC 2011: run
Thu Jan  5 17:59:00 UTC 2012: skip
Thu Jan 12 18:31:00 UTC 2012: run
Thu Jan 19 04:51:00 UTC 2012: skip
Thu Jan 26 08:02:00 UTC 2012: run
Thu Feb  2 17:37:00 UTC 2012: skip
Thu Feb  9 14:08:00 UTC 2012: run
Thu Feb 16 18:50:00 UTC 2012: skip
Thu Feb 23 15:52:00 UTC 2012: run

fuente
2
Segundos desde la época es inherentemente en UTC, mientras que cron se ejecuta en tiempo local. Si la zona horaria de su sistema no es UTC, esto generará confusión. ("¿Por qué no funciona? Oh, ya es viernes en UTC"). La existencia de horario de verano hace que trabajar alrededor de este mucho más difícil (aunque no imposible, ya que la fecha Cal decir la actual UTC)
Derobert
5

Una forma podría ser usar la atutilidad si está ejecutando Linux. Podrías poner esto al final de tu script:

at X + 2 weeks -f myscript

donde X es el momento en el que quieres ejecutar tu script. Para inicializar solo llame atpor el tiempo que desea ejecutarlo la primera vez y luego la declaración anterior sigue renovando su llamada programada.

gvkv
fuente
Si esto va a ser una solución a largo plazo no recomendaría la ejecución de este aunque a me gustaría crear una función en el script que iba a salir si se tiene que ejecutar
Paul
3

Si puede usar anacronen el sistema, las cosas serán mucho más simples. Para usarlo anacrondebe tenerlo instalado y también debe tener acceso de root. No funciona en sistemas más antiguos (es decir, RHEL 5.x), las versiones anteriores de ancron SOLO se ejecutan en el arranque. Funciona con sistemas más nuevos (es decir, RHEL 6.x).

Con anacron, uno puede programar trabajos de una manera más flexible, por ejemplo, ejecutar el trabajo X una vez por semana. También anacronejecuta trabajos cuando la computadora está disponible, es decir, no tiene que considerar cuándo el sistema está activo o inactivo.

Para ejecutar un script cada dos semanas, debe agregar una línea similar a la siguiente en / etc / anacrontab:

14 5 myScript script.sh

Echa un vistazo a la página del manual para más detalles.

memin
fuente
El uso anacrones claramente la solución más limpia de la OMI (a menos que tenga algunas consecuencias no deseadas para algunas personas).
JanC
0

No estoy seguro de si hay una manera más elegante de definir cada dos semanas, pero esto puede funcionar para usted.

00 06 1-7,15-21 * * test `date +\%a` = Thu && /path/to/script

Esto lanzará el script a las 6:00 am el primer y tercer jueves del mes.

pferate
fuente
2
Sin embargo, eso terminaría saltando una semana si hay un mes con 3 jueves.
David Z
1
¿Hay un mes que tenga solo 3 jueves? Aunque puedo verlo saltar una semana si hay 5 jueves. Se puede actualizar a 1-7,15-21,29-31, pero entonces sería dirigido back-to-back si no hubiera ninguna coincidencia para la última serie ...
pferate
1
Por 3 jueves, ¿quiso decir 3 jueves que se ejecutaría el script y no 3 jueves en total? Puede que lo haya leído mal la primera vez.
pferate
0

Lo ejecutaría todas las semanas y hacer que el script verifique si el número de la semana es un número impar: si es así, salga.

Esto necesitaría un poco más de reflexión para funcionar de diciembre a enero.

Quizás haga que el script establezca un archivo indicador de "última ejecución exitosa". Cuando se inicie la secuencia de comandos, compruebe que el archivo de marca se modificó por última vez hace 14 días.

Glenn Jackman
fuente