Parser de expressão cron explicado para não-DevOps (2026)
Parser de expressão cron explicado para não-DevOps
Você entrega uma pequena feature, precisa rodá-la todo dia útil às 9 da manhã e pega o cron. Após três tentativas falhas e um incidente de produção (o job rodou a cada minuto durante um fim de semana inteiro), agora está consultando uma referência de sintaxe de expressão cron pela quarta vez este mês. A tabela da Wikipédia é densa, as respostas do StackOverflow se contradizem e a resposta que sua AI assistant te deu não casa exatamente com o que seu scheduler de fato aceitou.
Este guia explica expressões cron a partir dos primeiros princípios para pessoas que não escrevem cron todo dia — product managers, founders, designers, analistas e developers backend que usam cron um punhado de vezes por ano e querem acertar sem memorizar arcanas. Vamos cobrir o Cron Parser do Ai2Done para visualizar qualquer expressão em português simples, mais as armadilhas que mordem até engenheiros experientes.
TL;DR
- Uma expressão cron são 5 campos: minuto hora dia-do-mês mês dia-da-semana — separados por espaços.
- A armadilha mais complicada: quando ambos dia-do-mês e dia-da-semana são especificados, cron Unix clássico os trata como OR (roda se qualquer um casar), que raramente é o que você quer.
- Use o Cron Parser do Ai2Done para traduzir qualquer expressão para português simples e ver as próximas 5-10 horas de execução antes de fazer deploy.
- Fuso horário importa: a maioria dos schedulers de cron roda em UTC; especifique seu fuso explicitamente no sistema chamador (Kubernetes CronJob, AWS EventBridge etc.).
- Caracteres especiais
* / , - L W ? #significam coisas diferentes em cron clássico vs. cron Quartz — escolha o dialeto certo para seu scheduler.
Por que isso é mais difícil do que parece
O cron Unix original de 1975 usava 5 campos. Schedulers modernos (Quartz, Kubernetes CronJobs, AWS EventBridge, schedules do GitLab, GitHub Actions) estendem ou modificam a sintaxe de jeitos incompatíveis. Há pelo menos 4 dialetos amplamente usados:
- Cron Unix clássico (5 campos, usado por
crontabno Linux/macOS) - Vixie cron (a implementação de facto do Linux, com algumas extensões)
- Cron Quartz (7 campos incluindo segundos e ano, usado por schedulers Java e AWS EventBridge)
- Kubernetes CronJob (5 campos, mas sem
?e tratamento de DST ligeiramente diferente)
Uma expressão cron que funciona perfeitamente num sistema pode falhar validação, rodar em horas inesperadas ou silenciosamente nunca disparar em outro. A pergunta “esta expressão é válida?” é genuinamente dependente de dialeto.
A segunda fonte de confusão: o framing “5 campos” assume que você lembra a ordem. A maioria dos engenheiros sob pressão lembra “tem um minuto e uma hora e... era dia ou mês primeiro?”. A ordem correta é minuto, hora, dia-do-mês, mês, dia-da-semana.
A terceira fonte: caracteres especiais interagem de jeitos não óbvios. 0 0 1,15 * 1-5 roda no dia 1 e 15 de todo mês, OU segunda a sexta (porque cron clássico faz OR entre dia-do-mês e dia-da-semana). Para conseguir “1 e 15, mas só se for dia útil”, você precisa do placeholder ? do cron Quartz.
Um bom parser de cron te mostra as próximas 5-10 horas de execução reais no seu fuso, para você fazer sanity-check do que a expressão de fato faz antes de fazer deploy para produção.
Os 5 campos explicados
* * * * *
│ │ │ │ │
│ │ │ │ └── Dia da semana (0-6 ou SUN-SAT; alguns dialetos usam 1-7)
│ │ │ └────── Mês (1-12 ou JAN-DEC)
│ │ └────────── Dia do mês (1-31)
│ └────────────── Hora (0-23)
└────────────────── Minuto (0-59)
Cada campo pode ser:
- Um número específico:
5(significa “este valor exato”) - Uma lista:
1,15,30(significa “qualquer um desses valores”) - Um intervalo:
1-5(significa “deste até aquele”) - Um passo:
*/15(significa “a cada N-ésimo valor começando de 0”) — então*/15no campo minuto é “0, 15, 30, 45” - Um curinga:
*(significa “todo valor”)
Padrões comuns uma vez que você sabe a sintaxe:
* * * * *— todo minuto (a famosa expressão “esqueci de especificar um schedule” que te acorda às 3 da manhã)*/5 * * * *— a cada 5 minutos0 * * * *— toda hora, na hora cheia0 9 * * *— todo dia às 9:000 9 * * 1-5— dias úteis às 9:00 (o job “horário comercial” do manual)0 0 1 * *— primeiro dia de todo mês à meia-noite0 0 * * 0— domingo à meia-noite (limite de semana)15 14 1 * *— 14:15 no primeiro de todo mês0 */6 * * *— a cada 6 horas (0, 6, 12, 18)
Método 1: Ai2Done Cron Parser (verificação visual antes do deploy)
O Cron Parser do Ai2Done traduz qualquer expressão para português simples e mostra as próximas 10 horas reais de disparo. O fluxo:
- Abra /tools/cron_parser em qualquer navegador.
- Cole sua expressão — ex.:
0 9 * * 1-5. - Veja instantaneamente:
- Português simples: “Às 09:00, de segunda a sexta”
- Próximas 10 horas de disparo no seu fuso local
- Um breakdown campo-por-campo mostrando o que cada parte casa
- Erros de validação para expressões impossíveis (ex.:
0 9 32 * *— não há 32º dia do mês)
- Mude dialeto entre cron clássico, Quartz, AWS EventBridge e Kubernetes se seu scheduler usa uma variante não padrão.
A ferramenta roda inteiramente no cliente usando a lib cronstrue para tradução legível por humanos e cron-parser para cálculo de próximo disparo. Sua expressão nunca toca um servidor.
Dica pro: antes de fazer deploy de qualquer job movido a cron para produção, cole a expressão no parser e confirme que pelo menos os próximos 3 horários de disparo casam com sua intenção. Isso pega o clássico erro “queria a cada 6 horas mas digitei 0 6 * * * que significa uma vez por dia às 6 da manhã” em 5 segundos.
Método 2: o site crontab.guru
Se você já está num navegador, crontab.guru é o padrão não oficial para explicação de cron. É uma ferramenta web de página única com a mesma feature core — cole expressão, veja português. Diferenças do Ai2Done parser:
- Roda no servidor (sua expressão é logada no log de acesso deles)
- Não mostra o breakdown campo-por-campo
- Só suporta cron clássico (sem Quartz, sem dialeto AWS EventBridge)
- Tem sido grátis e excelente por ~10 anos
Para expressões não sensíveis é uma escolha boa. Para expressões que podem vazar informação (ex.: uma expressão contendo nomes de campo customizados em alguns dialetos Quartz), o parser local é mais seguro.
Método 3: teste num scheduler de dry-run
Para jobs cron de alto risco (pipelines de dados, runs de billing, ações agendadas customer-facing), a abordagem de mais alta confiança é fazer deploy num ambiente de dry-run primeiro:
- Kubernetes: faça deploy do CronJob com
suspend: truee inspecione os próximos runs calculados viakubectl describe. - AWS EventBridge: crie a regra sem targets e olhe as
NextInvocationscalculadas. - Airflow / Dagster: use a UI do scheduler que sempre mostra os próximos 5-20 horários de disparo para qualquer schedule de DAG.
Isso pega edge cases que um parser não pega (offset UTC do seu cluster, transições de horário de verão, peculiaridades específicas do scheduler como a sintaxe cron(0 9 ? * MON-FRI *) do AWS EventBridge que exige 6 campos com um ?).
As armadilhas clássicas
Dia-do-mês e dia-da-semana são OR, não AND. 0 0 1 * 1 roda à meia-noite no dia 1 de todo mês, e toda segunda. Não “dia 1 só se for segunda”. Para conseguir AND, use o ? do cron Quartz para indicar “sem valor específico” — 0 0 1 * ? roda só no dia 1 independente do dia da semana.
*/N não é “a cada N unidades”. É “começando de 0, a cada N unidades”. Então */30 * * * * roda em :00 e :30 de toda hora, não “30 minutos depois do último run”. Para agendamento real de intervalo fixo, use uma fila de job (Celery, BullMQ, Sidekiq) — cron é fundamentalmente baseado em calendário, não em intervalo.
Defaults de fuso horário são não confiáveis. Cron Linux roda no fuso do sistema. Containers Docker tipicamente fazem default para UTC. AWS EventBridge faz default para UTC. Kubernetes CronJobs fazem default para o fuso do API server (frequentemente UTC). Se seu job precisa rodar “às 9 da manhã hora local”, configure o fuso explicitamente — não confie em defaults.
Horário de verão cria ghost runs. Quando os relógios adiantam às 2 da manhã, um job agendado para 2:30 não roda naquele dia. Quando os relógios atrasam, ele roda duas vezes. A maioria dos schedulers tem opções para lidar com isso (políticas de misfire do Quartz, concurrencyPolicy do Kubernetes); leia a doc do seu.
0 0 31 2 * — roda no dia 31 de fevereiro, que não existe. A maioria dos schedulers silenciosamente pula. Teste antes de fazer deploy.
Como construímos o parser (deep-dive técnico)
O Cron Parser do Ai2Done é construído sobre:
- cronstrue para tradução em português (best-in-class, suporta todos os dialetos principais, ~30 KB gzipped)
- cron-parser para calcular os próximos horários de disparo (lida com DST, anos bissextos, intervalos, passos corretamente)
- Um pequeno adapter de dialeto para traduzir sintaxe AWS EventBridge (
cron(0 9 ? * MON-FRI *)— 6 campos, ano opcional) para o formato esperado pelo parser subjacente - Web Crypto / SubtleCrypto não é usado — não há conteúdo sensível à segurança aqui; o parser é só tooling de conveniência
A escolha de design interessante: deliberadamente não oferecemos “construir um cron de um picker estilo Google Calendar”. Esse tipo de UI é ótimo para iniciantes mas tende a ensinar as pessoas o picker, não a sintaxe subjacente. Cron é denso mas aprendível em 20 minutos; preferimos te ajudar a lê-lo a escondê-lo.
FAQ
Q: Por que há 5 campos em alguns schedulers e 6 ou 7 em outros?
A: Cron Unix clássico tem 5 campos (minuto hora dia mês dia-da-semana). Quartz adiciona 2 mais: segundos na frente e ano no final (* * * * * * *). AWS EventBridge usa 6 campos com dia-da-semana/dia-do-mês exigindo que um seja ?. Escolha o dialeto que casa com seu scheduler.
Q: O que ? significa em expressões cron?
A: É uma extensão Quartz / AWS EventBridge significando “sem valor específico”. Usada em dia-do-mês e dia-da-semana para desambiguar quando só um deles deveria casar. Não suportada em cron Unix clássico.
Q: O que L significa em expressões cron?
A: Uma extensão Quartz para “last” (último). L em dia-do-mês significa “último dia do mês” (28/29/30/31 dependendo). 5L em dia-da-semana significa “última sexta do mês”. Útil para jobs de fim de mês sem hard-codar 28/29/30/31.
Q: O que W significa em expressões cron?
A: Uma extensão Quartz para “weekday” (dia útil). 15W em dia-do-mês significa “o dia útil mais próximo do 15” — útil para “folha de pagamento mensal, mas nunca num fim de semana”.
Q: Como rodo um job a cada 5 minutos só durante horário comercial?
A: */5 9-17 * * 1-5 — a cada 5 minutos, horas 9-17, dias úteis. Verifique com o parser; os próximos 10 horários de disparo deveriam casar com sua expectativa.
Q: Meu job rodou duas vezes durante a transição de horário de verão. Como conserto isso?
A: Isso é específico do scheduler. concurrencyPolicy: Forbid do Kubernetes CronJob previne runs sobrepostos. Quartz tem políticas de misfire. AWS EventBridge lida com DST sempre rodando em UTC (então horário de verão é problema da sua aplicação).
Q: Posso expressar “a primeira segunda de todo mês” em cron?
A: Em cron Unix clássico, não — você precisa de lógica em nível de aplicação. Em cron Quartz, sim: 0 0 0 ? * MON#1 (roda à meia-noite na primeira segunda de todo mês).
Experimente agora
Verifique qualquer expressão cron antes que rode em produção:
Cole, veja, faça deploy. Sem upload, sem signup, suas expressões ficam no seu navegador.
Leituras relacionadas
- Um debugger de JWT privacy-safe que nunca manda seu token — mesma arquitetura, aplicada a JWTs
- JSON, YAML, XML, CSV — round-tripping com um único toolbox — para os arquivos de config que seus jobs cron provavelmente consomem
- Processamento WASM no cliente: por que rodamos tudo no seu navegador
- Navegue por todas as ferramentas de developer
Última atualização 2026-06-14. O Cron Parser roda 100 % no seu navegador — suas expressões nunca deixam seu dispositivo. Não temos log de servidor do que você testou.