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.


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 .


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!"

+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


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

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

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"

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ê.


+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.


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


0

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

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

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. :-)


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.


Uma resposta foi aceite, é sua resposta melhor, diferente ou úteis sobre uma versão mais recente, etc.
mic84
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.