Executar um trabalho cron na primeira segunda-feira de cada mês?

32

Gostaria de executar um trabalho do cron às 8h30 na primeira segunda-feira de cada mês. A página cron da Wikipedia diz

Embora normalmente o trabalho é executado quando os / campos de especificação de data todos os tempos coincidir com a hora ea data atuais, há uma exceção: se ambos "dia do mês" e "dia da semana" são restritas (e não "*"), então quer o campo "dia do mês" (3) ou o campo "dia da semana" (5) deve corresponder ao dia atual.

(minha ênfase)

Isso significa que não posso fazer a primeira segunda-feira do mês, só posso fazer o primeiro (ou o que for) dia do mês? Não consigo pensar em uma maneira de contornar isso.

Max Williams
fonte
slhck - isso soa como uma boa solução - você se importaria de expandi-lo para uma resposta com o código completo? então eu vou marcá-lo como correto :)
Max Williams

Respostas:

39

Você pode colocar a condição no comando crontab real:

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

Agora, se essa condição for verdadeira em um dos primeiros sete dias em um mês, você terá sua primeira segunda-feira. Observe que, no crontab, a porcentagem de sintaxe precisa ser escapada:

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

Substitua o echocomando pelo comando que você deseja executar. Também encontrei uma abordagem semelhante .

slhck
fonte
na verdade, slhck, falei cedo demais - isso não está funcionando no meu crontab: parece ter um problema com o teste de data por algum motivo. Isso funciona na linha de comando [ "$(date '+%a')" = "Mon" ] && echo "It's Monday"como funciona [ $(date '+%a') = "Mon" ] && echo "It's Monday" Mas, no crontab, parece estar falhando neste teste. Eu não posso começar a qualquer feedback útil a partir do cron: i estou tentando isso [ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1para capturar qualquer saída de erro em um log, mas que não está funcionando ou: /
Max Williams
Hum. Você pode verificar se a datesaída está correta? Por exemplo, apenas permita que um croncomando execute isso em um arquivo: date '+%a' > ~/datetest 2>&1- verifique se isso resultou na string correta para comparação.
Slhck
11
Eu encontrei o problema - o por cento no +%aprecisava escapar quando ele estava no crontab, ou seja, a linha precisava ser este: [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday". Se você poderia atualizar sua resposta com que ele seria útil para futuros leitores :) Obrigado novamente - Max
Max Williams
Oh, agora eu vejo o porquê. Ainda bem que funciona agora, obrigado por experimentar!
Slhck
14

Eu tenho um computador com localidade em espanhol, portanto, essa abordagem não está funcionando para mim porque mon muda para lun

Outros idiomas também falharam, então fiz uma pequena variação na resposta aceita que elimina a barreira do idioma:

 0 9 1-7 * *   [ "$(date '+\%u')" = "1" ] && echo "¡Es lunes!"
cumanacr
fonte
+1 ¡Muy bien, senhor!
JakeGould # 25/18
11
Gracias ¡Pura vida! ; D
cumanacr
Essa deve ser a resposta aceita. Eu tenho uma localidade holandesa que também usa nomes diferentes para dias da semana. E usar números também parece mais limpo do que comparar cadeias para determinar o dia da semana.
0ne_Up
7

Acho mais fácil quando não há necessidade de lidar com os números dos dias.

Execute a primeira segunda-feira do mês:

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

ou seja, se o mês 1 semana atrás não for igual ao mês atual, estaremos no 1º dia 1 (= segunda-feira) do mês.

Da mesma forma, para a terceira sexta-feira

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

ou seja, se o mês 3 semanas atrás for diferente do mês atual, estaremos no terceiro dia 6 (= sexta-feira) do mês

joel
fonte
O dia 6 da semana é sábado, não sexta-feira.
Robert
4

Programei um trabalho para ser executado na 4ª segunda-feira de cada mês às 16:00 da seguinte maneira:

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

Até onde eu sei, NÃO é possível usar apenas o crontab, no entanto, pode-se usar uma função de wrapper para selecionar o dia correto a partir de uma entrada de contab dos "primeiros sete dias do mês"; veja isso na entrada.

O script do wrapper seria

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

e você precisaria executá-lo (assumindo que seja chamado wrapper.sh e disponível globalmente) usando a entrada crontab

0 0 * * 1 wrapper.sh
elemakil
fonte
obrigado elemaki. Pensei em uma solução semelhante usando algum código extra dentro da tarefa executada, testando se é a primeira segunda-feira do mês dentro do script e depois chamando-a toda segunda-feira no crontab. É um script ruby, por isso é fácil testar o dia da semana. Mas eu esperava que houvesse uma única maneira de crontab.
Max
1

No Solaris 10, tive que formatar a condição da seguinte maneira:

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

Você pode tentar executar o cronjob nos primeiros sete dias do mês e deixá-lo executar apenas na segunda-feira.

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

Acima deve funcionar para você.

simer
fonte
+1 mais sucesso atingiu a ração do que a primeira semana e a segunda-feira. :-)
xmedeko 22/03
1

Eu recomendo usar

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

ao invés de

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

para evitar problemas de localidade.

Manus Freedom
fonte
0

Eu fiz uma solução geral para esse tipo de problema, funciona pela primeira, segunda, terceira ..... última semana do mês.

Você pode usá-lo assim:

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"

O script run-if-today verifica o dia da semana e o período da semana desejado, se ambos corresponderem, retornará 0, caso contrário 1.

Verifique o código aqui. https://github.com/xr09/cron-last-sunday

MGP
fonte
0

Eu acredito que isso resolve o problema de maneira mais elegante:

30 8 1-7 * 1 /run/your/job.sh
symcbean
fonte
11
Doh! : "Se os dois campos forem restritos (por exemplo, não são *), o comando será executado quando um dos campos corresponder à hora atual."
symcbean
Também em fevereiro (o que termina em 28), não será executado a cada 4 anos.
Igraczech 05/10
"qualquer um" significa qualquer um deles, não "ambos". isso será executado todos os dias nos primeiros 7 dias do mês.
minusf 30/08/19
Essa linha executaria um comando no primeiro ao sétimo de cada mês, bem como toda segunda-feira
Tomasz Jakub Rup
0

Como interpreto minhas instruções cron usando php e js, não posso usar o bash. Finalmente, descobri que é de fato possível com apenas cron:

0 30 8 * 1/1 MON#1

Espero que isso ajude outra pessoa. Independentemente disso, desejo a todos um lindo dia. :-)

kramer65
fonte
Isso não é cron, é possivelmente quartzo
sivann 29/11
-1
0 9 1-7 * 1 * 

Isso funcionará para todas as segundas-feiras de cada mês.

SIBHI S
fonte
Uma resposta foi aceite, é sua resposta melhor, diferente ou úteis sobre uma versão mais recente, etc.
mic84