Preciso criar um trabalho CRON que será executado no último dia de cada mês. Vou criá-lo usando cPanel.
Qualquer ajuda é apreciada. obrigado
Preciso criar um trabalho CRON que será executado no último dia de cada mês. Vou criá-lo usando cPanel.
Qualquer ajuda é apreciada. obrigado
Respostas:
Possivelmente, a maneira mais fácil é simplesmente fazer três trabalhos separados:
55 23 30 4,6,9,11 * myjob.sh
55 23 31 1,3,5,7,8,10,12 * myjob.sh
55 23 28 2 * myjob.sh
No entanto, isso acontecerá no dia 28 de fevereiro, mesmo em anos bissextos, então, se isso for um problema, você precisará encontrar outra maneira.
No entanto, geralmente é substancialmente mais fácil e correto executar o trabalho o mais rápido possível no primeiro dia de cada mês, com algo como:
0 0 1 * * myjob.sh
e modifique o script para processar os dados do mês anterior .
Isso elimina quaisquer dificuldades que você possa encontrar para descobrir qual dia é o último do mês e também garante que todos os dados desse mês estejam disponíveis, presumindo que você esteja processando dados. Se correr cinco minutos para a meia-noite do último dia do mês, você poderá perder tudo o que acontece entre essa hora e a meia-noite.
Essa é a maneira usual de fazer isso de qualquer maneira, para a maioria dos trabalhos de fim de mês.
Se você ainda realmente deseja executá-lo no último dia do mês, uma opção é simplesmente detectar se amanhã é o primeiro (seja como parte do seu script ou no próprio crontab).
Então, algo como:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
deve ser um bom começo, supondo que você tenha um date
programa relativamente inteligente .
Se o seu date
programa não for avançado o suficiente para fornecer datas relativas, você pode simplesmente montar um programa muito simples para fornecer o dia do mês de amanhã (você não precisa de todo o poder de date
), como:
#include <stdio.h>
#include <time.h>
int main (void) {
// Get today, somewhere around midday (no DST issues).
time_t noonish = time (0);
struct tm *localtm = localtime (&noonish);
localtm->tm_hour = 12;
// Add one day (86,400 seconds).
noonish = mktime (localtm) + 86400;
localtm = localtime (&noonish);
// Output just day of month.
printf ("%d\n", localtm->tm_mday);
return 0;
}
e então use (supondo que você o tenha chamado tomdom
de "dia do mês de amanhã"):
55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh
Embora você possa considerar a adição de verificação de erros, pois ambos time()
e mktime()
pode retornar -1
se algo der errado. O código acima, por uma questão de simplicidade, não leva isso em consideração.
Existe um método ligeiramente mais curto que pode ser usado semelhante a um dos anteriores. Isso é:
[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"
Além disso, a entrada do crontab pode ser atualizada para verificar apenas no dia 28 ao 31, pois é inútil executá-lo nos outros dias do mês. O que lhe daria:
0 23 28-31 * * [ $(date -d +1day +%d) -eq 1 ] && myscript.sh
/bin/sh: -c: line 1: unexpected EOF while looking for matching ')'
.
[ $(date -d +1day +\%d) -eq 1 ] && run_job
posix
e a data POSIX não suporta "-d +1day"
: - \ Uma solução mais complicada (e feia) seria:[ `date +\%d` -eq `cal | xargs echo | awk '{print $NF}'` ] && myscript.sh
Configure um cron job para ser executado no primeiro dia do mês. Em seguida, altere o relógio do sistema para um dia adiantado.
Que tal este, depois da Wikipedia?
55 23 L * * /full/path/to/command
Adaptando a solução do paxdiablo, corro nos dias 28 e 29 de fevereiro. Os dados do dia 29 substituem o dia 28.
# min hr date month dow
55 23 31 1,3,5,7,8,10,12 * /path/monthly_copy_data.sh
55 23 30 4,6,9,11 * /path/monthly_copy_data.sh
55 23 28,29 2 * /path/monthly_copy_data.sh
,29
.
55 23 28 2
?
Você pode configurar um cron job para ser executado todos os dias do mês e fazer com que ele execute um script de shell como o seguinte. Este script descobre se o número do dia de amanhã é menor que o de hoje (ou seja, se amanhã é um novo mês) e faz o que você quiser.
TODAY=`date +%d`
TOMORROW=`date +%d -d "1 day"`
# See if tomorrow's day is less than today's
if [ $TOMORROW -lt $TODAY ]; then
echo "This is the last day of the month"
# Do stuff...
fi
Alguns implementações de cron suportam o sinalizador "L" para representar o último dia do mês.
Se você tiver sorte de usar uma dessas implementações, é tão simples como:
0 55 23 L * ?
Isso acontecerá às 23h55 do último dia de cada mês.
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
#########################################################
# Memory Aid
# environment HOME=$HOME SHELL=$SHELL LOGNAME=$LOGNAME PATH=$PATH
#########################################################
#
# string meaning
# ------ -------
# @reboot Run once, at startup.
# @yearly Run once a year, "0 0 1 1 *".
# @annually (same as @yearly)
# @monthly Run once a month, "0 0 1 * *".
# @weekly Run once a week, "0 0 * * 0".
# @daily Run once a day, "0 0 * * *".
# @midnight (same as @daily)
# @hourly Run once an hour, "0 * * * *".
#mm hh Mday Mon Dow CMD # minute, hour, month-day month DayofW CMD
#........................................Minute of the hour
#| .................................Hour in the day (0..23)
#| | .........................Day of month, 1..31 (mon,tue,wed)
#| | | .................Month (1.12) Jan, Feb.. Dec
#| | | | ........day of the week 0-6 7==0
#| | | | | |command to be executed
#V V V V V V
* * 28-31 * * [ `date -d +'1 day' +\%d` -eq 1 ] && echo "Tomorrow is the first today now is `date`" >> ~/message
1 0 1 * * rm -f ~/message
* * 28-31 * * [ `date -d +'1 day' +\%d` -eq 1 ] && echo "HOME=$HOME LOGNAME=$LOGNAME SHELL = $SHELL PATH=$PATH"
Para a implementação do AWS Cloudwatch cron (Scheduling Lambdas, etc.) isso funciona:
55 23 L * ? *
Funcionando às 23h55 do último dia de cada mês.
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job
Confira uma pergunta relacionada no fórum unix.com.
Você pode apenas conectar todas as respostas em uma linha cron e usar apenas o date
comando.
Basta verificar a diferença entre o dia do mês que é hoje e será amanhã:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
Se esta diferença for inferior a 0 significa que alteramos o mês e existe o último dia do mês.
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash
Que tal isso?
editar a .bashprofile
adição do usuário :
export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)
Em seguida, adicione esta entrada ao crontab:
mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
O último dia do mês pode ser 28-31 dependendo do mês (fevereiro, março, etc.). No entanto, em qualquer um desses casos, o dia seguinte é sempre o primeiro dia do mês seguinte. Portanto, podemos usar isso para garantir que executamos algum trabalho sempre no último dia do mês, usando o código abaixo:
0 8 28-31 * * [ "$(date +%d -d tomorrow)" = "01" ] && /your/script.sh