Pular para o conteúdo principal

Sintaxe de expressão cron

Uma expressão cron são cinco campos — minuto, hora, dia do mês, mês, dia da semana —, cada um contendo *, um número, um intervalo como 1-5, um passo como */15 ou uma lista como 1,3,5. Todos os campos se cruzam, exceto pela armadilha clássica: se você restringir o dia do mês e o dia da semana, o cron faz um OU entre eles, não um E. O horário segue o relógio do servidor.

Só local
Só quer a ferramenta? Abra Testar expressão cronVê o que a expressão significa e quando ela disparaAbrir ferramenta

Sintaxe de expressão cron: explicação

O cron é o agendador do Unix desde os anos 1970, e a sua gramática quase não mudou: cinco campos pequenos que, juntos, respondem “quando isto executa”. Você encontra a sintaxe em crontabs, sistemas de CI, Kubernetes CronJobs, planos de manutenção de banco de dados e metade dos agendadores da internet — uma sintaxe com idade para votar, que ainda vence porque cabe em uma linha.

A gramática é simples; as bordas não são. Todos os campos, menos um, se cruzam com os demais, e a exceção — dia do mês versus dia da semana — faz o oposto do que a intuição pede. Domingo responde tanto a 0 quanto a 7. Os amigáveis atalhos @daily são extensões, não fazem parte do padrão. E não há campo de fuso horário em nenhum lugar da sintaxe, então toda expressão herda em silêncio o relógio que o seu host usar.

Este guia percorre os cinco campos, os operadores, a armadilha dos campos de dia, os atalhos e a realidade dos fusos horários, terminando com como testar uma expressão antes de apostar um job de produção nela. O testador linkado aqui roda inteiramente no seu navegador — a expressão nunca sai da aba.

A maneira mais rápida de fixar essas regras é quebrá-las de propósito e observar a reação de um parser, então mantenha o testador de expressão cron aberto na aba ao lado: ele descreve o que a sua expressão significa e lista os próximos horários de execução, calculados localmente.

Agendamentos modernos costumam viver em arquivos de deploy em vez de crontabs, então, quando a sua expressão viaja dentro de uma definição de pipeline, o guia de fundamentos de YAML cobre as regras de indentação, aspas e tipagem que esse arquivo obedece.

Os cinco campos

Uma expressão cron padrão é exatamente cinco campos separados por espaços, em uma ordem fixa: minuto, hora, dia do mês, mês, dia da semana. Um job dispara quando todos os campos batem com o horário atual — os campos são combinados com um E. Escreva 30 4 * * * e o job roda às 04:30 todos os dias; todos os campos precisam concordar para o momento contar.

Cada campo aceita números dentro da sua faixa, e os campos de mês e de dia da semana também aceitam nomes — JAN-DEC e SUN-SAT —, que alguns agendadores aceitam sem diferenciar maiúsculas de minúsculas. As faixas valem a pena memorizar porque duas delas começam de um lugar inesperado: meses contam a partir de 1, e dias da semana contam a partir de 0. Todo o resto da sintaxe de cron são operadores aplicados sobre esses campos.

CampoPosiçãoValores permitidosNomes aceitos
Minuto1º0-59—
Hora2º0-23—
Dia do mês3º1-31—
Mês4º1-12JAN-DEC
Dia da semana5º0-7 (0 e 7 são ambos domingo)SUN-SAT

Intervalos, passos e listas

Três operadores fazem a maior parte do trabalho nas expressões reais. Um intervalo, 1-5, corresponde a todos os valores entre os extremos, inclusive. Um passo, escrito depois de uma barra, corresponde a cada N-ésimo valor do campo ou intervalo que o precede — */15 no campo de minutos significa 0, 15, 30, 45, e 9-17/2 no campo de horas significa a cada duas horas de 9 a 17. Uma lista, 1,3,5, corresponde exatamente aos valores nomeados, e os operadores se combinam: 1-5,10 e 0-30/5 são ambos válidos.

Dois hábitos mantêm os passos honestos. Primeiro, */N sempre inclui o mínimo do campo — então */15 atinge o minuto 0, e é por isso que frotas de jobs */15 acordam juntas no topo da hora. Segundo, um passo sobre um intervalo explícito costuma ser mais claro do que uma lista: 0-59/10 se lê como “a cada dez minutos” de um jeito que 0,10,20,30,40,50 não se lê.

ExpressãoLê-se como
0 9 * * 1-509:00, de segunda a sexta
*/15 * * * *A cada 15 minutos
0 0 1 * *Meia-noite no dia 1 de cada mês
30 4 1,15 * SUN04:30 no dia 1, no dia 15 e em todo domingo
0 22 * * 1-522:00 em dias de semana

Uma expressão, testada

30 9 * * 1-5

O que o testador diz

At 09:30, on Monday through Friday.
Next runs (UTC):
  Mon 2026-09-21 09:30
  Tue 2026-09-22 09:30

A armadilha do dia do mês versus dia da semana

Todo par de campos se cruza — exceto dia do mês e dia da semana, entre os quais o cron faz um OU sempre que ambos estão restritos. A surpresa clássica: 0 0 13 * 5 não significa “sexta-feira 13”. Significa meia-noite no dia 13 do mês, ou meia-noite em qualquer sexta — um job que roda duas vezes em algumas semanas e em datas que você nunca pretendeu. Se um dos campos de dia for *, o comportamento normal de E volta, e só o outro importa.

A regra do OU não é um bug; está escrita na documentação do POSIX e do Vixie cron, e sobrevive porque permite que os dois campos de dia sirvam a donos diferentes — um job mensal no dia 1 pode coexistir com um job semanal no domingo em um mesmo par de campos. Mas ela derrota a intuição, então os hábitos defensivos são: nunca restrinja os dois a menos que tenha contado os OUs, e quando precisar de verdade de “sexta-feira 13”, agende diariamente e teste a data no próprio comando.

Domingo é 0 e 7, e os atalhos são extensões

O dia da semana aceita tanto 0 quanto 7 para domingo no Vixie cron, a implementação de que descendem a maioria dos sistemas, e o 7 é convertido para 0 na entrada. É uma cortesia para intervalos — SUN-SAT pode ser escrito como 0-6 ou 1-7 —, mas é também uma costura de portabilidade: algumas outras implementações rejeitam o 7 de cara, e algumas particularidades de análise tornam o 7 arriscado em listas. Escrever 0 para domingo é a escolha portátil.

Os atalhos com @ — @reboot, @yearly, @annually, @monthly, @weekly, @daily, @midnight e @hourly — são, da mesma forma, extensões do Vixie, não fazem parte da gramática POSIX. Ainda assim, são suportados quase em todo lugar que alega compatibilidade com cron, o que os torna aceitáveis na prática, e continuam valendo a expansão mental: @daily é 0 0 * * *, meia-noite em todos os dias, e @reboot significa uma vez quando o daemon inicia, o que pode ser mais cedo ou mais tarde do que você espera após um reagendamento.

AtalhoExpande paraSignificado
@reboot—Uma vez, quando o daemon do cron inicia
@yearly / @annually0 0 1 1 *Meia-noite de 1º de janeiro
@monthly0 0 1 * *Meia-noite no dia 1 de cada mês
@weekly0 0 * * 0Meia-noite todo domingo
@daily / @midnight0 0 * * *Meia-noite todos os dias
@hourly0 * * * *No início de cada hora

O campo de fuso horário que não existe

O cron não tem campo de fuso horário. Uma expressão é avaliada contra o relógio do daemon — a hora local do sistema do servidor —, então o mesmo crontab significa horários diferentes em máquinas de zonas diferentes, e mover um job de um host em Tóquio para um em Frankfurt muda o agendamento em silêncio. Contêineres tornam isso mais agudo: a maioria roda em UTC independentemente de onde os operadores estejam, então “quando executa” e “quando eu quis dizer” se afastam por um deslocamento que ninguém anunciou.

O horário de verão adiciona os seus próprios perigos em qualquer zona de hora local: um job às 02:30 não existe na noite em que os relógios são adiantados, e um job às 01:30 roda duas vezes na noite em que são atrasados. Algumas implementações aceitam correções não portáveis — uma linha TZ ou CRON_TZ no crontab, ou um fuso horário na configuração do próprio agendador —, mas o suporte varia e a portabilidade termina onde essas linhas começam. A prática honesta é saber em qual relógio a sua expressão roda; o testador deste site calcula tudo em UTC e diz isso ao lado de cada resultado.

Testando uma expressão antes de colocá-la em produção

Algumas expressões são válidas e insatisfazíveis — 0 0 31 2 * pede 31 de fevereiro, e nenhum laço de busca ingênuo sobre datas jamais o encontra, e é por isso que um testador de verdade limita a busca por anos e reporta um agendamento que nunca dispara em vez de travar. Outras expressões são válidas e apenas não são o que você queria dizer; a armadilha do 13-ou-sexta produz agendamentos que parecem certos por dias antes de surpreender você.

O fluxo que detecta ambos: escreva a expressão, peça que ela seja descrita de volta em palavras e olhe os próximos horários concretos de execução. Uma descrição diz o que um parser acha que você escreveu; marcações de tempo concretas mostram onde ele vai disparar de fato. O testador deste site faz os dois — sintaxe padrão de cinco campos mais as variantes de seis e sete campos no estilo Quartz — inteiramente no seu navegador, então uma expressão que contenha nomes internos de jobs ou hostnames nunca sai da aba.

Perguntas frequentes

O testador de cron envia as minhas expressões ou nomes de jobs?

Não. A análise, a descrição e o cálculo das próximas execuções acontecem em JavaScript dentro da aba do seu navegador; a expressão nunca sai da sua máquina. Confirme no DevTools: abra o painel Network, avalie uma expressão e veja a lista de requisições permanecer vazia. A Content-Security-Policy do site também proíbe conexões de saída dos scripts da página.

Por que 0 0 13 * 5 não significa sexta-feira 13?

Porque o cron faz um OU entre os campos de dia quando ambos estão restritos: esse agendamento dispara à meia-noite no dia 13 do mês ou em qualquer sexta, o que vier primeiro — não na sexta-feira 13. É comportamento definido, tanto no POSIX quanto no Vixie cron. Para capturar a coincidência real, agende o job diariamente e teste a data no comando que ele executa.

7 é um valor válido para dia da semana?

No Vixie cron e seus descendentes, sim — tanto 0 quanto 7 significam domingo, com o 7 convertido para 0 na entrada. Mas é o canto menos portátil da sintaxe: algumas implementações rejeitam o 7 de cara, e ele se comporta de maneira estranha em listas e intervalos ali. Escrever 0 para domingo não custa nada e evita a discordância por completo.

Em que fuso horário uma expressão cron roda?

O relógio que o daemon usar — a hora local do sistema do servidor, já que o cron não tem campo de fuso horário. Contêineres geralmente significam UTC. Algumas implementações aceitam uma linha TZ ou CRON_TZ no crontab, mas isso não é portável, e zonas de hora local adicionam peculiaridades do horário de verão, em que jobs às 02:30 pulam uma noite e jobs às 01:30 rodam duas vezes. Conheça o relógio antes de confiar no agendamento.

Os atalhos @daily, @weekly e @reboot são padrão no cron?

São extensões do Vixie cron, não do POSIX, mas o suporte é quase universal em coisas que se dizem cron. Vale saber para o que expandem: @daily é 0 0 * * *, @weekly é 0 0 * * 0, e @reboot dispara quando o daemon inicia — o que, depois que uma máquina reagenda ou um contêiner reinicia, é quando isso acontecer, não um horário fixo.

Por que o meu job não roda no último dia do mês?

O cron não tem sintaxe de “último dia” — o dia do mês para em 31, e 31 corresponde apenas em sete meses do ano. A solução padrão é um pequeno teste de shell: agende para meia-noite todos os dias e rode apenas se amanhã for dia 1. Agendadores com calendários mais ricos (timers do systemd, Quartz com a sua flag L) expressam isso nativamente; o cron POSIX deliberadamente não.