it-swarm.it

Come posso dire a cron di eseguire un comando a giorni alterni (pari / dispari)

Quando configuri cron per eseguire un comando a giorni alterni utilizzando il campo "Giorno del mese", in questo modo:

1 22 */2 * * COMMAND

funziona ogni volta che il giorno del mese è dispari: 1,3,5,7,9 e così via.

Come posso configurare cron per l'esecuzione in giorni del mese che sono anche come 2,6,8,10 e così via (senza specificarlo letteralmente, il che è problematico poiché ogni mese ha un numero diverso di giorni nel mese)?

46
freddie

La sintassi che hai provato è in realtà ambigua. A seconda di quanti giorni sono nel mese, alcuni mesi verranno eseguiti in giorni dispari e alcuni in pari. Questo perché il modo in cui viene calcolato prende il numero totale di possibilità e le divide. È possibile ignorare questo comportamento strage specificando manualmente l'intervallo di giorni e utilizzando un numero pari o dispari di giorni. Poiché gli script dei giorni pari non verrebbero mai eseguiti il ​​31 ° giorno dei mesi più lunghi, non perdi nulla usando 30 giorni come base per i giorni pari e specificando specificamente di dividerlo come se ci fossero 31 giorni puoi forzare dispari -esecuzione giornaliera.

La sintassi sarebbe simile a questa:

# Will only run on odd days:
0 0 1-31/2 * * command

# Will only run on even days:
0 0 2-30/2 * * command

La tua preoccupazione per i mesi che non hanno lo stesso numero di giorni non è importante qui perché nessun mese ha PIÙ giorni di questo, e per febbraio povero, l'intervallo di date non corrisponderà mai all'ultimo giorno o due, ma non farà alcun male averlo elencato.

L'unico 'gotcha' per questo approccio è che se sei in un ciclo di giorni dispari, dopo mesi con 31 giorni il tuo comando verrà eseguito anche il primo del mese. Allo stesso modo se stai forzando un ciclo uniforme, ogni anno bisestile causerà un ciclo di tre giorni alla fine di febbraio. Non puoi davvero aggirare il fatto che qualsiasi modello regolare di "ogni altro giorno" non cadrà sempre nei giorni pari o dispari di ogni mese e in qualunque modo lo forzerai avrai una corsa extra o ti mancherà una corsa tra mesi con conteggi dei giorni non corrispondenti.

64
Caleb

Penso che una possibilità stia usando il giorno dell'anno, come questo:

# for odd days
test $(((`date +%j` % 2))) != 0 && command

# for even days
test $(((`date +%j` % 2))) == 0 && command

È testato per sistemi Unix e Linux.

2
Jordi

In generale, lo eseguivo ogni giorno e lo script usa la logica per determinare se dovrebbe essere eseguito oggi.

Creare un semplice file di stato che indichi l'ultima esecuzione e quindi il compairing funzionerebbe molto facilmente.

Se deve essere eseguito su origini diverse, rendilo dipendente dall'argomento.

1
Klas Mattsson

Controlliamo ogni giorno se è un "altro" :-) (bc programma richiesto)

0 0 * * * test $(echo `date +%s` / 86400 % 2 == 0 |bc) -eq 0 && command

(Non sono sicuro che il codice appaia correttamente. Il date +%s la parte è tra apostrofi posteriori.)

1
user37264