Publicado em · 9 min de leitura
Expressões Cron do Zero: Um Guia Visual
Aprenda a sintaxe cron POSIX de 5 campos, caracteres especiais, valores de passo, extensões Quartz, diferenças do cron da AWS e uma dúzia de exemplos prontos que você pode copiar e colar em um crontab hoje.
Por que cron ainda está em todo lugar
O cron foi escrito por Brian Kernighan para o Unix Versão 7 em 1979. A versão que a maioria dos sistemas Linux modernos ainda distribui — o Vixie cron, escrito por Paul Vixie em 1987 — adicionou variáveis de ambiente, crontabs por usuário e o amigável atalho @reboot, mas manteu o formato original de cinco campos quase intocado. Essa estabilidade é a razão exata pela qual uma sintaxe projetada antes da World Wide Web existir ainda é colada em manifests do Kubernetes, workflows do GitHub Actions, regras do AWS EventBridge e anotações @Scheduled do Spring em 2026.
Se você só aprende cron copiando linhas do Stack Overflow, o agendamento eventualmente faz algo inesperado — seu backup diário roda a cada minuto, seu job de fim de semana dispara nas terças, seu fuso horário muda em um limite de horário de verão. Este guia percorre a sintaxe desde a base e depois mostra exemplos suficientes para que você reconheça o formato de qualquer expressão de relance.
O formato de 5 campos
Uma linha de crontab POSIX é um agendamento seguido de um comando. O agendamento é exatamente cinco campos separados por espaços em branco: minuto, hora, dia do mês, mês, dia da semana. Cada campo aceita um número, uma lista, um intervalo, um passo ou o curinga *.
* * * * * comando-a-rodar
┬ ┬ ┬ ┬ ┬
│ │ │ │ │
│ │ │ │ └─── dia da semana (0-6, Domingo = 0; 7 também = Domingo na maioria das implementações)
│ │ │ └───── mês (1-12, ou JAN-DEC)
│ │ └─────── dia do mês (1-31)
│ └───────── hora (0-23)
└─────────── minuto (0-59)Caracteres especiais: * , - / e amigos
Cinco caracteres fazem quase todo o trabalho no cron clássico. Aprenda o que cada um significa e a maioria das expressões se lê como uma frase.
- * — todos os valores neste campo. * no campo minuto significa "a cada minuto".
- , — lista de valores discretos. 0,15,30,45 no campo minuto significa quatro minutos fixos por hora.
- - — intervalo inclusivo. 1-5 no campo dia da semana significa segunda a sexta.
- / — valor de passo, escrito como intervalo/passo ou */passo. */10 em minuto significa "a cada 10 minutos começando em 0".
- L, W, # — extensões do Quartz, não fazem parte do POSIX. L = último, W = dia útil mais próximo, # = enésimo dia da semana no mês. Mais sobre eles abaixo.
0,30 * * * * em :00 e :30 a cada hora
*/5 * * * * a cada 5 minutos (0, 5, 10, 15 ...)
0 9-17 * * 1-5 a cada hora das 09:00 às 17:00, Seg-Sex
0 0 1,15 * * meia-noite nos dias 1 e 15 de cada mês
15 14 * * 0 14:15 todo domingoValores de passo não são o que você pensa
O operador de passo / sempre funciona contra um intervalo, mesmo quando o intervalo é implícito. */15 no campo minuto é abreviação de 0-59/15, que dispara em 0, 15, 30 e 45. É por isso que */7 em minuto NÃO significa "a cada 7 minutos a partir de agora" — significa "os múltiplos de 7 entre 0 e 59", o que te dá 0, 7, 14, 21, 28, 35, 42, 49, 56 e depois uma lacuna de 4 minutos antes que a meia-noite vire. Se você precisa de um intervalo rolante verdadeiro, use um executor de jobs ou um timer do systemd com OnUnitActiveSec.
Passos também podem começar no meio de um intervalo. 5-59/10 em minuto dispara em 5, 15, 25, 35, 45, 55. Combine intervalos e passos quando quiser um agendamento não simétrico sem escrever uma lista gigante de vírgulas.
*/15 * * * * 00, 15, 30, 45 (bom)
*/7 * * * * 00, 07, 14, 21, 28, 35, 42, 49, 56, depois lacuna de 4 min (provavelmente não é o que você quer)
5-59/10 * * * * 05, 15, 25, 35, 45, 55
0 */4 * * * 00:00, 04:00, 08:00, 12:00, 16:00, 20:00Dia do mês e dia da semana: a regra do OR
A maior cilada do cron: quando tanto dia do mês quanto dia da semana estão restritos (nenhum é *), o Vixie cron os trata como um OR lógico, não AND. A linha 0 0 13 * 5 dispara à meia-noite no dia 13 de cada mês E toda sexta-feira — não apenas na sexta-feira 13. Para obter o comportamento de AND, restrinja apenas um dos dois campos e filtre o outro no seu script, ou use um agendador como o Quartz que suporta o placeholder ? para "nenhum valor específico".
0 0 13 * 5 meia-noite no dia 13 OU em qualquer sexta (regra OR do Vixie cron)
0 0 * * 5 toda sexta à meia-noite
0 0 13 * * todo dia 13 do mês à meia-noite
# Quartz: 0 0 0 13 * 5 ? combinaria sexta-feira 13 especificamenteDez exemplos para copiar e colar
Imprima essa tabela e cole ao lado do seu monitor. A maioria das linhas cron de produção que você escreverá são variações menores destas.
* * * * * a cada minuto
0 * * * * a cada hora em :00
*/15 * * * * a cada 15 minutos
0 0 * * * todo dia à meia-noite (hora local do servidor)
0 9 * * 1-5 dias úteis às 09:00
30 14 * * 1-5 dias úteis às 14:30
0 9 * * 1 toda segunda às 09:00
0 22 * * 0 todo domingo às 22:00
0 0 1 * * meia-noite no dia 1 de cada mês
0 0 1 1 * meia-noite em 1º de janeiro
0 3 * * 6 todo sábado às 03:00 (janela típica de backup)
*/5 9-17 * * 1-5 a cada 5 minutos no horário comercial, Seg-SexAtalhos nomeados
O Vixie cron, o GNU mcron e a maioria dos descendentes aceitam alguns aliases prefixados com @ que mapeiam para agendamentos comuns. São mais fáceis de ler do que os cinco campos equivalentes e mais difíceis de errar.
@yearly igual a 0 0 1 1 * (também @annually)
@monthly igual a 0 0 1 * *
@weekly igual a 0 0 * * 0
@daily igual a 0 0 * * * (também @midnight)
@hourly igual a 0 * * * *
@reboot rodar uma vez no boot do sistemaQuartz: o primo de 6 e 7 campos
Os agendadores Java — o próprio Quartz, o @Scheduled do Spring com cron =, e algumas plataformas de nuvem — usam um dialeto diferente. O Quartz prefixa um campo de segundos e opcionalmente anexa um campo de ano, dando a você seis ou sete campos no total. Também suporta L (último), W (dia útil mais próximo), # (enésimo dia da semana do mês) e o placeholder ? que significa "nenhum valor específico, apenas um entre dia do mês e dia da semana está definido".
Se você copia uma expressão Quartz para um crontab Linux, ela será analisada incorretamente em silêncio, porque o 0 inicial parece um valor de minuto normal para o Vixie cron. Sempre saiba qual dialeto seu agendador espera antes de salvar o arquivo.
Campos Quartz: segundo minuto hora dia-do-mês mês dia-da-semana [ano]
0 0 12 * * ? todo dia ao meio-dia
0 15 10 ? * MON-FRI dias úteis às 10:15
0 0 0 L * ? último dia de cada mês à meia-noite
0 0 0 LW * ? último dia útil de cada mês
0 0 9 ? * 2#1 primeira segunda de cada mês às 09:00
0 0 9 ? * 6#3 terceira sexta de cada mês às 09:00
0 0 0 1 * ? 2026 meia-noite no dia 1 de cada mês, mas apenas em 2026Expressões rate vs cron na AWS
EventBridge, CloudWatch Events e Lambda usam uma sintaxe cron quase Quartz com dois desvios importantes. Não há campo de segundos (seis campos, não sete) e você deve usar ? em dia-do-mês ou dia-da-semana — nunca ambos como *. A AWS também oferece rate(valor unidade) para intervalos simples, o que evita a cilada do OR inteiramente.
Campos cron da AWS: minuto hora dia-do-mês mês dia-da-semana ano
cron(0 12 * * ? *) todo dia às 12:00 UTC
cron(0/15 * * * ? *) a cada 15 minutos
cron(0 9 ? * MON-FRI *) dias úteis às 09:00 UTC
cron(0 0 1 * ? *) meia-noite UTC no dia 1 de cada mês
rate(5 minutes) a cada 5 minutos
rate(1 hour) a cada hora
rate(7 days) a cada 7 dias a partir da criação da regraFusos horários, horário de verão e o que quebra às 02:30
O Vixie cron respeita o fuso horário do sistema (variável de ambiente TZ, ou o que /etc/localtime aponta). Quando o horário de verão pula uma hora para frente, qualquer job agendado dentro da lacuna é silenciosamente pulado. Quando o horário de verão volta atrás, jobs agendados dentro da hora duplicada rodam duas vezes em algumas implementações e uma vez em outras. Os dois padrões seguros: rode o cron em UTC, ou agende fora da janela 01:00-04:00.
Agendadores de nuvem se comportam diferentemente. O EventBridge sempre roda em UTC. O Kubernetes CronJobs respeita o campo spec.timeZone adicionado no v1.27. O Quartz usa o padrão da JVM a menos que você passe um CronTrigger com fuso horário. Sempre leia a documentação uma vez para qualquer que seja o agendador que você está configurando; não presuma que a convenção do último vale para o próximo.
Depurando uma expressão que não dispara
Nove em dez vezes a expressão em si está bem e o ambiente é que está errado. Percorra este checklist antes de culpar o agendamento.
- Leia o log do daemon do cron: grep CRON /var/log/syslog no Debian/Ubuntu, journalctl -u cron em hosts com systemd. O log mostra a linha de comando resolvida que o cron de fato executou.
- Confirme o usuário. crontab -l sem flag mostra o SEU crontab; o agendamento que te interessa pode estar em /etc/crontab, /etc/cron.d/*, ou no crontab de outro usuário.
- Verifique o PATH. O cron roda com um PATH mínimo (geralmente /usr/bin:/bin). Use caminhos absolutos ou defina PATH= no topo do crontab.
- Verifique o shell. O cron usa /bin/sh, não o seu shell de login. Qualquer coisa específica do bash (substituição de processo, [[ )) precisa de um wrapper bash -c explícito.
- Redirecione a saída. Sem > /var/log/myjob.log 2>&1 um job que falha envia e-mail para root localmente e você nunca o vê.
- Confirme o fuso horário. date && date -u dentro do job loga ambos. Se eles discordam do que seu agendamento assumiu, esse é o seu bug.
# Uma linha cron mais segura:
SHELL=/bin/bash
PATH=/usr/local/bin:/usr/bin:/bin
MAILTO=""
*/5 * * * * /usr/local/bin/sync.sh >> /var/log/sync.log 2>&1Quando o cron é a ferramenta errada
O cron é excelente para agendamentos fixos de relógio de parede e imbatível para jobs de uma linha em um único host. Ele é uma má escolha quando você precisa de: coordenação distribuída entre muitas máquinas (use uma fila, um agendador com eleição de líder, ou Kubernetes CronJobs com concurrencyPolicy: Forbid); retries e back-off em falha (envelope o script ou use um motor de workflow); granularidade sub-minuto (use um timer systemd ou um gatilho orientado a evento); ou agendamentos que dependem da execução anterior terminar primeiro (o cron felizmente iniciará uma segunda cópia enquanto a primeira ainda está rodando). Reconhecer o limite cedo poupa muitas paginações às 3 da manhã.
Construa e verifique visualmente
Se você escreve mais do que algumas linhas cron por mês, o hábito de maior alavancagem é checar cada expressão contra um parser antes de fazer o commit. O Multilities oferece uma /tools/cron-builder gratuita que decodifica uma expressão de 5 ou 6 campos em inglês simples e mostra os próximos dez disparos no seu fuso horário local, que é exatamente a verificação cruzada que pega a armadilha do OR de dia do mês/dia da semana e a surpresa do passo estilo */7. Combine isso com um teste unitário rápido que afirma o próximo disparo para uma data âncora conhecida e seus jobs agendados se tornam entediantemente confiáveis — que é exatamente o que você quer deles.