Ir para o conteúdo
Allin

Como escrever uma expressão cron: cinco campos e a regra OU que ninguém menciona

Publicado a 21/05/2026 · 10 min de leitura · Ferramentas para programadores

Daniel Okonkwo

Daniel OkonkwoProgramador front-end e redator de Tecnologia na Allin

Desempenho web · Formatos de ficheiro

Verificado a partir de 2 fontes

Ver perfil
Em resumo

Uma expressão cron são cinco campos separados por espaços, lidos da esquerda para a direita: minuto (0-59), hora (0-23), dia do mês (1-31), mês (1-12 ou nomes de três letras) e dia da semana (0-6 em POSIX com 0 para domingo, alargado a 0-7 pela maioria das implementações de modo que 7 também é domingo). Um asterisco designa todos os valores do intervalo daquele campo. Um hífen forma um intervalo inclusivo: 8-11 no campo da hora é 8, 9, 10 e 11. Uma vírgula forma uma lista, e listas e intervalos misturam-se: 1-3,7-9. Uma barra acrescenta um passo, e é aí que se erra à primeira — um passo percorre um intervalo, não define uma cadência: */15 no campo dos minutos é 0, 15, 30 e 45, e */40 é 0 e 40 e depois nada até a hora seguinte reiniciar o intervalo. A segunda armadilha, maior, é que o dia do mês e o dia da semana se combinam com OU e não com E. Se ambos estiverem restringidos, a tarefa corre quando qualquer um dos dois corresponder. Portanto 0 0 1 * 1 não significa a primeira segunda-feira do mês: dispara à meia-noite do dia 1 de cada mês E à meia-noite de todas as segundas-feiras. Para fixar uma tarefa a um dia da semana concreto, deixe o dia do mês como asterisco, e vice-versa. Tudo o resto que encontrar — @daily, um sexto campo de segundos, o carácter ?, L, W e # — está fora da norma e depende inteiramente do cron que está a correr.

Minuto, hora, dia do mês, mês, dia da semana. As armadilhas: um passo é um avanço dentro de um intervalo e não um período, e os dois campos de dia combinam-se com OU — pelo que 0 0 1 * 1 dispara no dia 1 e em todas as segundas-feiras.

Cinco campos, e um passo não é uma cadência

Leia os campos da esquerda para a direita e a notação cabe na cabeça. O asterisco representa todo o intervalo do seu campo. O hífen forma um intervalo inclusivo: 8-11 no campo da hora são quatro horas, não três. A vírgula forma uma lista, e listas e intervalos combinam-se livremente no mesmo campo: 1-3,7-9 é um conjunto legal de seis valores. Os nomes podem substituir os números nos campos do mês e do dia da semana, com três letras, embora o cron Vixie clássico não aceite intervalos nem listas construídas com nomes — 1-3 é interpretado onde JAN-MAR pode falhar, boa razão para ficar pelos números em tudo o que deva ser portável.

A barra é onde o modelo mental parte. Um passo percorre um intervalo, não é uma cadência de repetição, e o intervalo recomeça no início de cada unidade superior. No campo dos minutos, */15 percorre 0, 15, 30, 45, depois a hora vira e recomeça em 0 — o que calha ser exatamente de quinze em quinze minutos, pelo que ninguém nota a diferença. Escreva */40 e a ilusão desaba: percorre 0 e 40, depois a hora vira e recomeça em 0, dando intervalos de quarenta minutos e depois de vinte. O mesmo para um intervalo limitado: 0-23/2 no campo da hora são as horas pares, e 1-9/2 são 1, 3, 5, 7 e 9. Se precisar mesmo de uma cadência que não divide a sua unidade, o cron não a consegue exprimir numa linha: precisa de duas entradas ou de uma guarda dentro do comando.

Os dois campos de dia combinam-se com OU, não com E

Esta é a regra que quase todas as explicações erram, e não é uma esquisitice de uma implementação: está escrita na especificação. A POSIX estabelece que, se o dia do mês for dado como elemento ou lista e o dia da semana também, então qualquer dia que corresponda ao dia do mês ou ao dia da semana é considerado. O manual crontab(5) diz o mesmo em palavras mais simples e dá o exemplo canónico: 30 4 1,15 * 5 corre às 4h30 da manhã no dia 1 e no dia 15 de cada mês, mais todas as sextas-feiras. Não o dia 1 ou o 15 quando calham a uma sexta. Ambos os conjuntos, reunidos.

As regras práticas que daí decorrem são curtas. Se exatamente um dos dois campos de dia for um asterisco, manda o outro e não há ambiguidade — é o caso que deve escrever quase sempre. Se ambos forem asteriscos, todos os dias correspondem, o que também é inequívoco. Só quando ambos estão restringidos é que a união entra em jogo, e o resultado quase nunca é o pretendido: 0 0 1 * 1 dispara cerca de cinco vezes por mês em vez de uma. Não existe sintaxe cron para a interseção, portanto se precisar mesmo da primeira segunda-feira do mês, o truque padrão é agendar a união e estreitá-la dentro do comando — correr em 0 0 1-7 * 1 e abrir o script com um teste de que o dia da semana é segunda, ou em 0 0 * * 1 com um teste de que o dia do mês é 7 ou menos. Os cron de estilo Quartz acrescentam um operador # para isto, mas não está disponível no cron do sistema.

Tudo o que vai além dos cinco campos depende da implementação

A POSIX define cinco campos, o asterisco, os intervalos, as listas e mais nada. Cada comodidade que tenha visto para lá disso é uma extensão, e as extensões variam. O passo com barra é uma extensão Vixie hoje quase universal mas ainda ausente da norma. As cadeias abreviadas — @yearly e o seu sinónimo @annually, @monthly, @weekly, @daily e o seu sinónimo @midnight, @hourly, e @reboot — vêm da mesma linhagem, e @reboot em particular não tem significado fixo entre sistemas, porque o que conta como reinício depende do serviço. Um sexto campo para os segundos é comum em agendadores de aplicação como Quartz, Spring e várias bibliotecas Node, e ausente do cron de sistema: uma expressão copiada da documentação de uma framework para um crontab ficará desfasada de um campo e agendará outra coisa por completo em vez de falhar de forma ruidosa.

O ponto de interrogação pertence à mesma família. No Quartz significa nenhum valor específico e existe precisamente para resolver a ambiguidade entre dia do mês e dia da semana declarando um campo irrelevante; o cron de sistema não o aceita de todo. Os operadores L, W e # para último dia do mês, dia útil mais próximo e enésimo dia da semana são igualmente exclusivos do Quartz. Dois factos do ambiente contam mais do que toda esta sintaxe: o serviço executa as tarefas no fuso horário para que está configurado, pelo que uma expressão correta numa instalação pode disparar uma hora antes ou depois noutra, e numa mudança de hora uma tarefa agendada na hora suprimida pode não correr de todo, enquanto uma na hora repetida pode correr duas vezes. E o cron é um gatilho, não um executor de tarefas — sem repetições, sem controlo de concorrência e sem memória de que a execução anterior falhou. Se duas invocações não podem sobrepor-se, adquira por si mesmo um bloqueio dentro do comando.

Os cinco campos, por ordem, com o erro que cada um convida
PosiçãoCampoValores permitidosO erro que convida
1.ºMinuto0-59Escrever * aqui quando queria 0 — uma expressão como * 3 * * * corre sessenta vezes, a cada minuto da hora das 3 da manhã
2.ºHora0-23Raciocinar em relógio de 12 horas: não existe 24 nem pm, meia-noite é 0 e as 11 da noite são 23
3.ºDia do mês1-31Usar 31 esperando doze execuções por ano: os meses mais curtos simplesmente nunca correspondem, pelo que a tarefa salta em silêncio fevereiro, abril, junho, setembro e novembro
4.ºMês1-12, ou JAN a DECSupor que os nomes funcionam em todo o lado: o cron Vixie clássico aceita nomes de três letras mas rejeita intervalos ou listas deles, pelo que JAN-MAR pode não ser analisado onde 1-3 é
5.ºDia da semana0-6 em POSIX com 0 para domingo; 0-7 na maioria das implementações, onde 7 também é domingoRestringir este campo e o dia do mês ao mesmo tempo: os dois combinam-se com OU, pelo que a tarefa dispara nos dois conjuntos de dias e não na sua interseção
Gerador de expressão cronConstrói um agendamento cron campo a campo — minuto, hora, dia do mês, mês, dia da semana — e vê a expressão e a descrição em linguagem clara atualizarem-se ao vivo. As predefinições cobrem os casos comuns e a sintaxe (*, */5, 1-5, 1,15) é explicada.Experimentar a ferramenta

Perguntas frequentes

O que significa exatamente */15?
No campo dos minutos seleciona os valores 0, 15, 30 e 45 — um passo de quinze através do intervalo 0 a 59, a começar no primeiro valor do intervalo. Não é um temporizador que dispara quinze minutos depois da última execução, e não sobrevive a uma divisão inexata: */40 no campo dos minutos seleciona apenas 0 e 40, pelo que os intervalos são de quarenta minutos e depois de vinte quando a hora seguinte reinicia o intervalo. Se quiser uma cadência medida desde a última execução e não desde o início da hora, o cron é a ferramenta errada: um temporizador systemd com OnUnitActiveSec, ou um ciclo dentro de um processo de longa duração, é a certa.
Como corro uma tarefa a cada 90 minutos?
Não numa só linha, porque 90 não divide 60 e um passo fica confinado a um único campo. O padrão repete-se, porém, de três em três horas, pelo que duas entradas o cobrem exatamente: 0 */3 * * * dá as 00:00, 03:00, 06:00 e assim por diante, e 30 1-23/3 * * * dá as 01:30, 04:30, 07:30 e assim por diante. Juntas produzem uma execução a cada noventa minutos, e a sequência fecha de forma limpa à meia-noite porque vinte e quatro horas são exatamente dezasseis intervalos de noventa minutos. O mesmo truque de duas entradas serve para qualquer cadência que divida um número inteiro de horas; o que não o faz, como a cada 50 minutos, não pode ser expresso em cron de todo.
Porque é que a minha tarefa noturna correu duas vezes, ou nenhuma?
A causa habitual é uma mudança de hora. O cron compara a hora do relógio de parede: quando o relógio avança, uma hora que nunca existiu nunca é cumprida e uma tarefa agendada lá dentro simplesmente não corre; quando o relógio recua, uma hora ocorre duas vezes e uma tarefa agendada lá dentro pode disparar duas vezes. As implementações diferem no esforço de compensação, e por isso o mesmo crontab comporta-se de forma diferente em duas distribuições. As correções fiáveis são agendar as tarefas sensíveis fora da janela de transição, correr o serviço num fuso sem mudanças de hora, ou tornar o próprio comando seguro para correr duas vezes. Esta última compensa de qualquer forma: a idempotência protege-o também de repetições, execuções sobrepostas e relançamentos manuais.

Artigos que podem interessar-lhe

Todos os guias
ExplicaçãoComo funcionam as permissões de ficheiro em Unix: ler 755 sem adivinharLeitura 4, escrita 2, execução 1, e cada um dos três dígitos descreve uma parte diferente. O que quase todas as explicações erram é o que o bit de execução faz num diretório: concede a passagem, não o direito de executar seja o que for.GuiaCódigos de estado HTTP explicados: os que realmente se confundem301 contra 308, 302 contra 307, 401 contra 403, 404 contra 410 — e o que promete realmente o Retry-After num 429 ou num 503. Os pares em que escolher o código errado muda o comportamento, não apenas a redação.ExplicaçãoO que é uma expressão cron?Uma expressão cron agenda uma tarefa para correr automaticamente a horas definidas. Eis para que serve, os seus cinco campos, como lê-la, e os erros comuns.TutorialComo escrever um robots.txt: diretivas, correspondência e o que não consegue esconderQuatro diretivas, dois caracteres universais, um ficheiro na raiz do host. É uma instrução de rastreio e nada mais: não retira uma página dos resultados, não restringe o acesso e publica cada caminho que nele enumera.ExplicaçãoO que uma percentagem de disponibilidade permite realmenteTrês noves soa a promessa até se dividir em minutos. O que 99,9 % compra por ano, por mês, por semana e por dia; porque é que a janela de medição conta muito mais do que o nove a mais; e os dois meses diferentes que esta ferramenta usa para o mesmo identificador.ExplicaçãoA hora dourada e a hora azul são ângulos, não horasA hora dourada vai de +6° a −4° de altura do sol e a hora azul de −4° a −6°, razão pela qual dura quarenta minutos no equador, mais de uma hora em latitudes médias, e acima de 72,6° em junho não acontece de todo. Os limiares desta calculadora, verificados na sua própria saída.

Ferramentas relacionadas

Fontes

Detetaste um erro neste artigo?