Uma expressão cron é a forma mais concisa de dizer a um computador “execute esta coisa neste agendamento”. Cinco campos, todos números e caracteres especiais, sem ambiguidade uma vez que você aprenda a sintaxe. O problema: existem cerca de quinze padrões comuns que você realmente precisa, e o resto do tempo você fica encarando um prompt crontab -e tentando lembrar se domingo é 0 ou 7.
Este post é a referência que eu gostaria de ter tido cinco anos atrás. Todo padrão comum, com uma expressão copiar-e-colar, uma explicação e uma nota sobre a armadilha que pega as pessoas.
Os cinco campos
* * * * *
│ │ │ │ │
│ │ │ │ └── dia da semana (0-6, domingo=0)
│ │ │ └──── mês (1-12)
│ │ └────── dia do mês (1-31)
│ └──────── hora (0-23)
└────────── minuto (0-59)
Cada campo pode ser:
- Um valor específico:
5 - Um curinga:
*(todo valor) - Um intervalo:
1-5 - Um passo:
*/15(a cada 15) - Uma lista:
1,15,30 - Um intervalo com passo:
1-30/5(a cada 5 entre 1 e 30)
É só isso. O resto é combinar esses primitivos.
Os padrões
A cada minuto
* * * * *
Caso de uso: um job que deve estar sempre rodando e o agendador está apenas reiniciando-o. Raramente é o que você quer.
A cada N minutos
*/5 * * * * # a cada 5 minutos
*/15 * * * * # a cada 15 minutos
*/30 * * * * # a cada 30 minutos
O */5 significa “começando no 0, a cada 5 minutos”. Então 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55.
Armadilha: a primeira execução de */5 é no minuto 0, não no momento em que você salvou o crontab. Se você salvar às 12:03, a primeira execução é 12:05, não 12:08.
A cada hora em ponto
0 * * * *
Armadilha: isto é “minuto 0 de cada hora”, ou seja, 1:00, 2:00, 3:00, etc. Se você quer “a cada hora, 30 minutos depois”, use 30 * * * *.
Todo dia à meia-noite
0 0 * * *
Armadilha: o fuso horário do servidor. cron usa o fuso horário do sistema. Se seu servidor está em UTC e você quer meia-noite no horário do leste dos EUA, precisa converter. A solução mais limpa: configure o fuso horário do sistema para o que você quer, ou defina a variável de ambiente CRON_TZ (suportada pela maioria das implementações modernas de cron).
Todo dia em um horário específico
0 9 * * * # 9:00 AM
30 14 * * * # 2:30 PM
0 0 * * * # meia-noite
15 3 * * * # 3:15 AM
Todo dia útil às 9h
0 9 * * 1-5
O 1-5 é dia da semana, segunda a sexta-feira.
Armadilha: 0 e 7 significam domingo. A especificação POSIX aceita ambos. A maioria das implementações tolera se você acidentalmente usar 7. Não confie nisso.
Toda segunda-feira
0 0 * * 1
Meia-noite toda segunda-feira.
Duas vezes por semana (segunda e quinta)
0 9 * * 1,4
9h de segunda e quinta-feira.
Primeiro dia de cada mês
0 0 1 * *
Meia-noite no dia 1.
Último dia do mês
0 0 L * *
O L é uma extensão do Vixie cron / Quartz. O cron padrão não tem isso. Se você está usando cron padrão, fica com aproximações para “último dia” como 0 0 28-31 * * (que executa nos dias 28, 29, 30 e 31, e no dia 28 de fevereiro).
A cada trimestre
0 0 1 */3 *
Meia-noite no dia 1 de janeiro, abril, julho e outubro.
Todo domingo ao meio-dia
0 12 * * 0
A cada 6 horas
0 */6 * * *
0:00, 6:00, 12:00, 18:00.
A cada minuto entre 9h e 17h, dias úteis
* 9-17 * * 1-5
Um job que executa a cada minuto das 9:00:00 às 17:59:59, de segunda a sexta-feira. Provavelmente agressivo demais — mas possível.
Às 2:30 AM no primeiro dia de cada mês
30 2 1 * *
Às 23h na última sexta-feira do mês
0 23 * * 5#5
O 5#5 é “5ª sexta-feira do mês” (sintaxe Quartz). O # e o L são extensões não padrão — o cron padrão não tem uma expressão “última sexta-feira do mês”. Se você precisa disso no cron padrão, precisa de um script wrapper que verifique a data.
A cada 30 segundos
O cron padrão não vai abaixo de 1 minuto. Para agendamento sub-minuto:
- systemd timers:
OnUnitActiveSec=30s - Em Kubernetes CronJob: não possível (mínimo de 1 minuto). Use um Job regular com
sleep 30em um loop. - Em um app Node.js:
setInterval(fn, 30_000)dentro do processo.
Horário de verão
O cron lida com o horário de verão executando o job duas vezes (adiantando no Spring) ou pulando-o (atrasando no outono), dependendo da implementação. Se seu job é sensível ao tempo (uma faturamento, um relatório), agende-o bem fora da janela de 1-3h para evitar surpresas com horário de verão.
O agendador Quartz lida com isso usando a flag DST. O cron padrão não.
O limite de granularidade de 1 minuto
O cron é fundamentalmente uma ferramenta com resolução de 1 minuto. Se você precisa de agendamento sub-minuto, a resposta é “use uma ferramenta diferente”. Para Kubernetes especificamente:
apiVersion: batch/v1
kind: CronJob
metadata:
name: every-30-seconds
spec:
schedule: "* * * * *"
startingDeadlineSeconds: 10
jobTemplate:
spec:
template:
spec:
containers:
- name: worker
image: myworker:latest
command: ["/bin/sh", "-c", "for i in 1 2; do do_work; sleep 30; done"]
Isso executa o job a cada 30 segundos emitindo dois sub-jobs por minuto. Cru, mas funciona.
E Quarkus, EventBridge, Kubernetes CronJob?
Diferentes agendadores usam sintaxes cron levemente diferentes. A forma de cinco campos é a mais comum. Alguns outros:
- Quartz: seis campos (com segundos), e o curinga
?para “nenhum valor específico”. - AWS EventBridge: seis campos, suporta as extensões
Le#. - Kubernetes CronJob: cinco campos, sem suporte a
Lou#. - Spring
@Scheduled: seis campos (com segundos), suporte a?eL. - GitHub Actions: cinco campos, sem extensões.
Se você está usando uma ferramenta que não corresponde ao padrão, verifique a documentação. A maioria dos padrões nesta referência se transfere diretamente. As extensões não padrão (L, #, W) não.
Gerando expressões cron sem memorizar sintaxe
Se você não quer memorizar a sintaxe, o cron generator no DevSpeedTools permite clicar através dos cinco campos e mostra as próximas cinco execuções agendadas. É a maneira mais rápida de verificar “0 9 * * 1-5 realmente significa 9h nos dias úteis?” — a resposta é sim, mas ver as próximas datas de execução torna o padrão concreto.
Para expressões pontuais, crontab.guru é a referência padrão. O cron generator faz o mesmo trabalho e é totalmente client-side, então as expressões que você cola nunca saem do seu navegador.
O resumo
Expressões cron são uma DSL minúscula com algumas regras. Aprenda os cinco campos, aprenda * (qualquer), - (intervalo), / (passo) e , (lista), e você pode expressar 95% dos agendamentos que precisará. Os outros 5% precisam de extensões específicas do agendador ou de uma ferramenta diferente. Em caso de dúvida, gere e visualize a expressão com uma ferramenta que mostra as próximas execuções — muito mais rápido que debugar mentalmente.