Eseguire un processo cron il primo lunedì di ogni mese?


32

Vorrei eseguire un lavoro da cron alle 8.30 del primo lunedì di ogni mese. Dice la pagina di cron di Wikipedia

Mentre normalmente il lavoro viene eseguito quando l'ora / data campi di specifica tutti i match l'ora e la data corrente, c'è un'eccezione: se entrambi "giorno del mese" e "giorno della settimana" sono limitate (non "*"), allora sia il campo "giorno del mese" (3) o il campo "giorno della settimana" (5) devono corrispondere al giorno corrente.

(la mia enfasi)

Significa che non posso fare il primo lunedì del mese, posso fare solo il primo (o qualunque altro) giorno del mese? Non riesco a pensare a un modo per aggirarlo.


slhck - sembra una buona soluzione - ti dispiacerebbe espanderlo in una risposta con il codice completo? poi lo segnerò come corretto :)
Max Williams,

Risposte:


39

È possibile inserire la condizione nel comando crontab effettivo:

[ "$(date '+%a')" = "Mon" ] && echo "It's Monday"

Ora, se questa condizione è vera in uno dei primi sette giorni in un mese, hai il suo primo lunedì. Si noti che nel crontab, la sintassi percentuale deve essere sfuggita però:

0   12  1-7 *   *   [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday"

Sostituisci il echocomando con il comando effettivo che desideri eseguire. Ho trovato anche un approccio simile .


in realtà, slhck, ho parlato troppo presto - questo non funziona nel mio crontab: sembra avere un problema con il test della data per qualche motivo. Questo funziona nella riga di comando [ "$(date '+%a')" = "Mon" ] && echo "It's Monday"come fa [ $(date '+%a') = "Mon" ] && echo "It's Monday" Ma, nel crontab sembra fallire in questo test. Neanche io posso ottenere alcun feedback utile da cron: sto provando questo [ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1per catturare qualsiasi output di errore in un registro ma non funziona neanche: /
Max Williams

Hm. Puoi verificare se l' dateoutput è corretto? Ad esempio, basta croneseguire un comando che lo genera in un file: date '+%a' > ~/datetest 2>&1- quindi verificare se ciò ha comportato la stringa corretta per il confronto.
Slhck,

1
Ho trovato il problema - la percentuale in +%anecessario fuggire quando era in crontab, vale a dire la linea doveva essere questo: [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday". Se potessi aggiornare la tua risposta con ciò sarebbe utile per i futuri lettori :) Grazie ancora - max
Max Williams

Oh, ora capisco perché. Sono contento che funzioni ora, grazie per averlo provato!
Slhck,

15

Ho un computer con impostazioni locali sul spagnolo, quindi, questo approccio non funziona per me, perché mon cambia a lun

Anche altre lingue fallirebbero, quindi ho fatto una leggera variazione sulla risposta accettata che elimina la barriera linguistica:

 0 9 1-7 * *   [ "$(date '+\%u')" = "1" ] && echo "¡Es lunes!"

+1 ¡Muy bien, señor!
Jake Gould il

1
Gracias ¡Pura vida! ; D
cumanacr,

Questa dovrebbe essere la risposta accettata. Ho un locale olandese che usa anche nomi diversi per i giorni feriali. Inoltre, utilizzare i numeri risulta più pulito rispetto al confronto delle stringhe per determinare il giorno della settimana.
0ne_Up,

7

Lo trovo più facile quando non è necessario gestire i numeri dei giorni.

Esegui il primo lunedì del mese:

0 2 * * 1 [ `date '+\%m'` == `date '+\%m' -d "1 week ago"` ] || /path/to/command

cioè se il mese 1 settimana fa non è lo stesso del mese corrente, allora siamo al 1 ° giorno 1 (= lunedì) del mese.

Allo stesso modo, per il terzo venerdì

0 2 * * 6 [ `date '+\%m'` == `date '+\%m' -d "3 weeks ago"` ] || /path/to/command

cioè se il mese 3 settimane fa è diverso dal mese corrente, allora siamo al 3 ° giorno 6 (= venerdì) del mese


Il giorno 6 della settimana è sabato non venerdì.
Robert

4

Ho programmato un lavoro da eseguire il 4 ° lunedì di ogni mese alle 16:00 come segue:

0 16 22-28 * Mon [ "$(date '+\%a')" == "Mon" ] && touch /home/me/FourthMonOfMonth.txt

1

Per quanto ne so NON è possibile utilizzare solo crontab, tuttavia è possibile utilizzare una funzione wrapper per selezionare il giorno corretto da una voce contab "primi sette giorni del mese"; vedere questo dalla voce.

Lo script wrapper sarebbe

#! /usr/bin/ksh
day=$(date +%d)
if ((day <= 7)) ; then
   exec somecommand
fi
exit 1

e dovresti eseguirlo (supponendo che sia chiamato wrapper.sh e disponibile a livello globale) usando la voce crontab

0 0 * * 1 wrapper.sh

grazie elemaki. Ho pensato a una soluzione simile usando un codice aggiuntivo all'interno dell'attività che viene eseguito, facendolo testare se è il primo lunedì del mese all'interno dello script e quindi chiamandolo ogni lunedì in crontab. È una sceneggiatura ruby, quindi è facile testare il giorno della settimana. Ma speravo che ci sarebbe stato solo un crontab.
Max Williams,

1

Su Solaris 10 ho dovuto formattare la condizione come segue:

[ `date +\%a` = "Sat" ] && echo "It's Saturday"

1

Puoi provare a eseguire cronjob per i primi sette giorni del mese e lasciarlo eseguire solo il lunedì.

30 8 * * 1 [`date +\%d` -le 07] && <job>

Sopra dovrebbe funzionare per te.


+1 razione di successo in più rispetto alla corsa per la prima settimana e controllo per lunedì. :-)
xmedeko

1

Consiglio di usare

"$(/bin/date '+%\w')" = "1"

invece di

"$(date '+\%a')" = "Mon"

per evitare problemi di localizzazione.


0

Ho fatto una soluzione generale per questo tipo di problemi, funziona per primo, secondo, terzo ..... ultimo giorno della settimana del mese.

Puoi usarlo in questo modo:

30 06 * * Mon run-if-today 1 "Mon" && echo "First Monday"
30 06 * * Thu run-if-today 3 "Thu" && echo "Third Thursday"
30 06 * * Sun run-if-today L "Sun" && echo "Last Sunday"

Lo script run-if-today controlla sia l'intervallo di giorni della settimana sia quello desiderato, se entrambi corrispondono quindi restituisce 0, altrimenti 1.

Controlla qui il codice. https://github.com/xr09/cron-last-sunday


0

Credo che questo risolva il problema in modo più elegante:

30 8 1-7 * 1 /run/your/job.sh

1
Doh! : "Se entrambi i campi sono limitati (cioè non lo sono *), il comando verrà eseguito quando uno dei campi corrisponde all'ora corrente."
symcbean,

Anche a febbraio (quello che termina il 28) non verrà eseguito ogni 4 anni.
igraczech,

"entrambi" indica uno di essi, non "entrambi". questo verrà eseguito ogni giorno per i primi 7 giorni del mese.
meno

Questa riga eseguiva un comando dal primo al settimo di ogni mese, nonché ogni lunedì
Tomasz Jakub Rup

0

Dato che interpreto le mie dichiarazioni cron usando php e js, non posso usare bash. Alla fine ho scoperto che è infatti possibile solo con cron:

0 30 8 * 1/1 MON#1

Spero che questo aiuti qualcun altro. Indipendentemente da ciò, auguro a tutti una bellissima giornata. :-)


Questo non è cron, forse è quarzo
sivann

-1
0 9 1-7 * 1 * 

Funzionerà per ogni lunedì di ogni mese.


È stata accettata una risposta, la risposta è migliore, diversa o utile in una versione più recente, ecc.
mic84
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.