Por um único ano do calendário
Use duas linhas crontab. Saída de utilitário de data recebe o dia do ano
(date + \% j) e a saída bc atribui um 0, 1 ou 2 ao dia com aritmética remanescente (o operador de módulo). Embora a configuração possa ser qualquer propagação de 36 horas, uma configuração de exemplo é executar o trabalho às 6h nos 1 dias, às 18h no dia seguinte, que será de 2 dias, e nos 0 dias não executará o trabalho. / p>
0 6 * * * jd='/bin/date +\%j'; /usr/bin/test '/bin/echo "$jd"\%3 | /usr/bin/bc' -eq 1 && job
0 18 * * * jd='/bin/date +\%j'; /usr/bin/test '/bin/echo "$jd"\%3 | /usr/bin/bc' -eq 2 && job
Você pode testar isso na linha de comando com algo como
jd='/bin/date +\%j'; /usr/bin/test '/bin/echo "$jd"%3 | /usr/bin/bc' -eq 2 && echo 'yes'
Substitua jd por um dia de destino do ano e o 2 em "-eq 2" com 0 ou 1 para ver os resultados de um determinado dia. Por exemplo, em 2016, dias do ano 1-3 e 364-366:
1%3 = 1 364%3 = 1
2%3 = 2 365%3 = 2
3%3 = 0 366%3 = 0
Portanto, usando o cron, os utilitários de data e teste e bc como mostrado no exemplo acima, o trabalho será executado às 6h nos dias 1 e 364 de 2016, novamente às 18h nos dias 2 e 365 e não será executado nos dias 3 e 366.
Contabilidade da versão corrigida para anos sem saltos
Um comentarista generoso e outra resposta revelaram que a resposta acima falha para todos os anos, exceto um ano bissexto (2016, 2020). Isso ocorre porque o padrão remanescente não se mantém ao longo dos limites do ano após anos não bissextos (365 dias por ano). Portanto, o padrão restante precisa ser coagido em um padrão de 4 anos, em vez de um padrão de um ano.
O teste de linha de comando muito mais feio para o padrão de 4 anos é
jd='/bin/date +\%j';ya='/bin/date +\%Y';/usr/bin/test '/bin/echo if \("ya"%4\) 4-"ya"%4+"jd"%3 else "jd"%3 | /usr/bin/bc' -eq 0 && /bin/echo 'yes'
que, se o trabalho tiver que ser executado a cada 36 horas (por exemplo, como mostrado, às 6h de um dia, às 18h do dia seguinte e às 6h do dia seguinte) pode ser executado com duas linhas crontab conforme mostrado no exemplo único ano civil, isso é
0 6 * * * jd='/bin/date +\%j';ya='/bin/date +\%Y';/usr/bin/test '/bin/echo if \("ya"%4\) 4-"ya"%4+"jd"%3 else "jd"%3 | /usr/bin/bc' -eq 1 && job_to_run
0 18 * * * jd='/bin/date +\%j';ya='/bin/date +\%Y';/usr/bin/test '/bin/echo if \("ya"%4\) 4-"ya"%4+"jd"%3 else "jd"%3 | /usr/bin/bc' -eq 2 && job_to_run
Duas advertências merecem menção:
- Embora isso funcione com a versão stock bc na versão do Ubuntu que estou usando, a instrução else depende de extensões não POSIX para bc. Se essas extensões não POSIX não forem incorporadas em sua versão bc de ações, há uma solução alternativa, mas estou com preguiça de descobrir isso. Como isso é "Ask Ubuntu", eu me sinto seguro supondo que você esteja usando o Ubuntu Bc com as extensões não POSIX.
- Se o seu sistema estiver sobrecarregado com um fuso horário Daylight Savings, você precisará de 6 linhas crontab, cada uma para os intervalos de datas afetados pelo horário de verão, contabilizando o ganho e a perda de uma hora. Os intervalos de datas podem ser especificados com os campos cron.
Explicação narrativa
Assumo familiaridade com o uso de campos crontab (caso contrário, há sempre a página man). As duas linhas mostradas executarão "job" às 6h e 18h se a expressão de teste fornecida após os cinco campos de data e hora for bem-sucedida. A expressão de teste é bem sucedida da seguinte forma.
Vou explicar a expressão de teste mais complicada, porque a expressão mais simples é parte da expressão mais complicada.
- O utilitário de data é usado para preencher o dia do ano (1-366) e o ano (por exemplo, 2016) nas variáveis "jd" e "ya":
jd='/bin/date +\%j';ya='/bin/date +\%Y'
-
Em seguida, a saída de uma equação bc é testada (com / usr / bin / test). Se o resultado do cálculo de bc for igual a 1 ("-eq 1"), o trabalho será executado às 6h. Se o resultado do cálculo de bc for igual a 2, o trabalho será executado às 18h. Se o resultado do cálculo de bc for igual a qualquer outro número, incluindo 0, o trabalho não será executado.
-
Em seguida, o utilitário echo é usado para enviar a equação bc para o utilitário bc.
-
Primeiro, a equação bc é uma declaração "if". Se o resultado de bc avaliar a equação em parens após o "if", ("ya"%4)
, for diferente de zero, a próxima equação, 4-"ya"%4+"jd"%3
, será avaliada; caso contrário, a equação após "else", "jd"%3
, será avaliada.
-
Em todos os casos, "ya" é substituído pelo número do ano atual e "jd" é substituído pelo número do dia atual.
-
Para a condição "if", o resultado é o restante após dividir o ano por 4. Para 2016, o restante é 0, então a equação "else" é calculada. Para 2017, o restante é 1, para 2018, o restante é 2 e, para 2019, o restante é 3. Portanto, para 2017-2019 (mas não para 2016 ou 2020), a equação 4-"ya"%4+"jd"%3
é calculada. No caso de 2017, o resultado de 4-2017% 4 é 3 (4-1); em 2018, o resultado é 2 e, em 2019, o resultado é 1. Esse resultado é adicionado ao número do dia antes de dividir o número do dia por 3 para obter o restante usado para testar se o trabalho deve ou não ser executado.
-
Os padrões de 1,2,0 resultantes do cálculo testado de bc para os dias 1-3 e 363-365 em 2017-2019 são mostrados aqui:
2017 2018 2019
3 + 1 % 3 = 1 2 + 1 % 3 = 0 1 + 1 % 3 = 2
3 + 2 % 3 = 2 2 + 2 % 3 = 1 1 + 2 % 3 = 0
3 + 3 % 3 = 0 2 + 3 % 3 = 2 1 + 3 % 3 = 1
3 + 363 % 3 = 0 2 + 363 % 3 = 2 1 + 363 % 3 = 1
3 + 364 % 3 = 1 2 + 364 % 3 = 0 1 + 364 % 3 = 2
3 + 365 % 3 = 2 2 + 365 % 3 = 1 1 + 365 % 3 = 0
- Isso mostra que o padrão 0,1,2 no final de 2017 é repetido no início de 2018 e, do mesmo modo, 2,0,1 no final de 2018 e no início de 2019. O padrão mostrado acima em " Para um único ano civil "mostra que o padrão no final de 2016 e no início de 2020, 1,2,0, se repete no início de 2017 e no final de 2019.