Como construir expressões cron
As expressões cron são a forma padrão de definir horários recorrentes em Linux, plataformas na nuvem, pipelines CI/CD e agendadores de tarefas. A sintaxe é compacta mas pouco intuitiva: construir um gerador cron visual mostra-lhe exatamente quando a sua tarefa será executada, apanha erros comuns antes do deploy e elimina a adivinhação da parte mais propensa a erros da automação. Uma vez compreendidos os cinco campos, os caracteres especiais e as armadilhas mais comuns, pode especificar qualquer horário recorrente com confiança.
Uma breve história do cron
O primeiro cron veio de Brian Kernighan na versão 7 do Unix, por volta de 1979. Relia a sua configuração a cada minuto e executava o que estivesse pendente. Paul Vixie reescreveu-o em 1987 para o que hoje se chama Vixie cron, a versão que a maioria das distribuições Linux ainda usa. O Vixie cron acrescentou crontabs por utilizador, variáveis de ambiente, a palavra-chave @reboot e várias funcionalidades de conforto que tornaram o formato utilizável para não-administradores.
A sintaxe de 5 campos quase não mudou em mais de quarenta anos. Amazon EventBridge, Google Cloud Scheduler, Kubernetes CronJob, GitHub Actions, GitLab CI, Jenkins, Airflow, n8n e dezenas de outros sistemas consomem o mesmo formato compacto com apenas pequenas extensões. Essa estabilidade é a razão pela qual cron vale a pena aprender uma vez e nunca mais ter de reaprender. A competência transfere-se para todo o lado onde a automação corre por relógio.
Sintaxe cron
Uma expressão cron padrão tem 5 campos, separados por espaços. Cada campo controla uma fatia de tempo, e uma tarefa corre sempre que todos os campos correspondem ao momento atual.
┌───────────── minuto (0-59)
│ ┌───────────── hora (0-23)
│ │ ┌───────────── dia do mês (1-31)
│ │ │ ┌───────────── mês (1-12, ou JAN-DEC)
│ │ │ │ ┌───────────── dia da semana (0-6, Dom=0, ou SUN-SAT)
│ │ │ │ │
* * * * *
Os campos são combinados com E para hora, minuto e mês, mas dia-do-mês e dia-da-semana são combinados com OU no Vixie cron. Isto significa que 0 12 1 * 1 dispara no dia 1 de cada mês E em todas as segundas-feiras ao meio-dia, não apenas nas segundas-feiras que calham no dia 1. Esta armadilha apanha quase toda a gente da primeira vez.
Horários cron comuns
Os padrões a que vai recorrer com mais frequência:
| Horário | Expressão | Significado |
|---|---|---|
| Cada minuto | * * * * * | Corre a cada 60 segundos |
| Cada 5 minutos | */5 * * * * | Em :00, :05, :10, :15... |
| Cada 15 minutos | */15 * * * * | Em :00, :15, :30, :45 |
| Cada hora | 0 * * * * | No início de cada hora |
| Cada 2 horas | 0 */2 * * * | Em 00:00, 02:00, 04:00... |
| Diariamente à meia-noite | 0 0 * * * | Uma vez por dia às 00:00 |
| Diariamente às 9h | 0 9 * * * | Uma vez por dia às 09:00 |
| Duas vezes por dia | 0 9,21 * * * | Às 09:00 e 21:00 |
| Toda segunda às 8h | 0 8 * * 1 | Semanal, à segunda |
| Dias úteis às 18h | 0 18 * * 1-5 | De segunda a sexta |
| Dia 1 de cada mês | 0 0 1 * * | Mensal, à meia-noite do dia 1 |
| Cada trimestre | 0 0 1 */3 * | 1 jan, 1 abr, 1 jul, 1 out |
| Cada manhã útil | 0 7 * * 1-5 | 07:00 segunda-sexta |
| Domingo ao meio-dia | 0 12 * * 0 | Semanal, ao domingo |
Muitos sistemas também aceitam aliases abreviados que expandem para a expressão de 5 campos equivalente: @yearly, @monthly, @weekly, @daily, @hourly e @reboot. São concisos mas não universais, por isso verifique a sua plataforma antes de confiar neles.
Como construir uma expressão cron
- Escolha a granularidade: precisa de cada minuto, cada hora, uma vez por dia, uma vez por semana ou uma vez por mês? Comece pelo ajuste mais grosseiro que cobre a sua necessidade.
- Use os controlos visuais: selecione valores de minuto, hora, dia, mês e dia da semana nos dropdowns. Ou comece com uma predefinição como "cada hora" ou "diário à meia-noite" e ajuste.
- Pré-visualize as próximas execuções: o gerador mostra os próximos 5 horários de execução, o que lhe permite confirmar que o horário dispara quando espera.
- Confirme o fuso horário: a pré-visualização deve corresponder ao fuso do servidor ou agendador que vai correr a tarefa, não à sua hora local.
- Copie a expressão e cole na sua crontab, YAML do GitHub Actions, regra do AWS EventBridge ou qualquer agendador que use.
- Teste primeiro com um intervalo curto antes de fixar o horário final. Um rápido
*/5 * * * *prova que a tarefa dispara; assim que vir duas ou três execuções, mude para a expressão real.
Caracteres e operadores especiais
O cron suporta um conjunto pequeno mas poderoso de operadores dentro de qualquer campo.
| Caractere | Significado | Exemplo |
|---|---|---|
* | Qualquer valor | * * * * * = cada minuto |
*/n | Cada n | */15 * * * * = cada 15 min |
, | Vários valores discretos | 0 8,12,18 * * * = 8h, meio-dia, 18h |
- | Intervalo inclusivo | 0 9-17 * * * = cada hora 9h-17h |
n-m/k | Intervalo com passo | 0 9-17/2 * * * = 9, 11, 13, 15, 17 |
? | Sem valor específico (só Quartz) | 0 0 ? * MON (agendadores Java) |
L | Último (AWS, Quartz) | L em DoM = último dia do mês |
W | Dia útil mais próximo (AWS, Quartz) | 15W = dia útil mais próximo do dia 15 |
# | Enésimo dia da semana (AWS, Quartz) | MON#2 = segunda segunda-feira do mês |
@hourly | Atalho | O mesmo que 0 * * * * |
O Vixie cron clássico só suporta as primeiras cinco linhas. Os operadores avançados (L, W, #, ?) vêm do Quartz, a biblioteca de agendamento Java, e foram adotados pelo AWS EventBridge e por alguns outros agendadores cloud. Não são portáveis, por isso não os misture com código que tem de correr numa caixa Linux genérica.
Cron em diferentes plataformas
O cron é uma família de sintaxes relacionadas, não um padrão único. Saber que dialeto fala o seu agendador poupa horas de depuração.
| Plataforma | Campos | Notas |
|---|---|---|
| Vixie cron (Linux) | 5 | O clássico. */n, intervalos, listas, sem operadores avançados |
| BSD cron | 5 | Como Vixie mas com ligeiras diferenças de ambiente |
| crontab.guru | 5 | Analisador web que reflete a semântica Vixie |
| GitHub Actions | 5 | Sintaxe Vixie, corre em UTC, resolução mínima de 5 minutos |
| GitLab CI | 5 | Sintaxe Vixie, corre no fuso da instância |
| AWS EventBridge | 6 | Acrescenta ano. Dia da semana usa 1-7 (Dom=1), suporta L/W/# |
| Google Cloud Scheduler | 5 | Sintaxe Vixie mais configuração de fuso |
| Kubernetes CronJob | 5 | Sintaxe Vixie com atalhos @ |
| Quartz (Java) | 6 ou 7 | Acrescenta segundos no início e ano opcional |
| Timers do systemd | Formato OnCalendar | Não é cron, mas resolve o mesmo problema com sintaxe mais clara |
Se escrever um horário que tenha de correr em mais do que uma plataforma, fique pelo subconjunto conservador de 5 campos que todos os sistemas entendem. Use L, W ou # só quando souber que o destino os suporta.
Armadilhas comuns
- Dia-do-mês e dia-da-semana são combinados com OU, uma expressão como
0 9 15 * 1dispara em todas as segundas-feiras E no dia 15 de cada mês, não só no dia 15 quando calha à segunda. Para intersetar, normalmente precisa de um wrapper externo ou de outro agendador. - Confusão de fuso horário, as crontabs de servidor correm quase sempre em UTC. Se quer 9h hora do Leste, isso é
0 14 * * *UTC no inverno mas0 13 * * *UTC no verão por causa do horário de verão. Use um agendador que aceite dicas de fuso, ou normalize tudo para UTC. - Transições de horário de verão, tarefas agendadas às 02:30 hora local podem correr duas vezes quando os relógios atrasam e nenhuma quando adiantam. Agende tarefas sensíveis fora da janela 01:00-03:00 ou use UTC.
- A armadilha
MAILTOdo Vixie, se a sua tarefa imprime alguma coisa para stdout, o Vixie cron envia a saída por e-mail ao utilizador dono da crontab. Em servidores sem relay de e-mail isto enche depressa/var/spool/mail. Redirecione a saída para um ficheiro de log com>>/var/log/myjob.log 2>&1. - O ambiente não é a sua shell de login, o cron corre com um ambiente despojado: sem
PATHdo seu.bashrc, sem virtualenv, semnvm. Defina as variáveis de que precisa no topo da crontab ou chame o seu script com caminho absoluto. - Sinais de percentagem precisam de escape, um
%sem escape numa crontab Vixie é interpretado como caractere de nova linha no comando. Escape-o sempre como\%se o seu comando precisar de um percentagem literal, por exemplo numa invocaçãodate +"%Y-%m-%d". - Tarefas longas sobrepõem-se, o cron não salta uma execução porque a anterior ainda está a correr. Se a sua tarefa pode demorar mais que o intervalo, envolva-a num ficheiro de lock (
flock,setlock) ou use um executor que trate de concorrência. - Overflow nos 59 minutos,
*/40 * * * *não dispara cada 40 minutos. Dispara no minuto 0 e no 40 de cada hora porque os valores de passo dão a volta nos limites do campo. Para intervalos reais de 40 minutos precisa de um agendador mais rico. - Esquecer o
0no campo minuto,* 9 * * *corre todos os minutos das 09:00 às 09:59, não uma vez às 09:00. O campo minuto precisa de um valor explícito se quer um único disparo por hora. - O cron é pouco fiável em portáteis, o anacron existe por essa razão. O Vixie cron não recupera execuções perdidas após uma suspensão, por isso um backup diário agendado para as 03:00 não corre se o portátil estiver fechado nessa hora. Use anacron, timers do systemd com
Persistent=true, ou um plist do launchd no macOS.
Alternativas ao cron
Para algumas cargas a resolução grosseira ao minuto do cron e a ausência de contabilidade começam a doer. As melhorias mais comuns:
| Ferramenta | Força | Quando escolher |
|---|---|---|
| Timers do systemd | Sintaxe OnCalendar clara, persistente entre reinícios, integra com units | Já usa systemd e quer logging mais rico |
| Anacron | Recupera execuções perdidas após suspensão | Portáteis ou máquinas que não estão sempre ligadas |
| Airflow / Dagster | Dependências DAG, retentativas, observabilidade | Pipelines de dados multi-passo |
| Temporal | Workflows com estado, garantias exatamente-uma-vez | Orquestração de longa duração entre serviços |
| AWS EventBridge | Gerido, integra com Lambda, S3, SQS | Tudo o que é cloud-nativo na AWS |
| GitHub Actions | Gratuito para repositórios públicos, corre em runners hospedados | Tarefas agendadas adjacentes ao CI |
| funções serverless com triggers cron | Sem servidor para manter | Tarefas leves que cabem num Lambda |
O cron continua a ser a resposta certa para a grande maioria das tarefas recorrentes pontuais. As outras ferramentas brilham quando precisa de estado, retentativas, dependências ou coordenação entre máquinas.
Privacidade e o gerador cron
O gerador de expressões cron corre inteiramente no seu browser. O horário que constrói, a pré-visualização das próximas execuções e a expressão copiada nunca tocam os nossos servidores. Não há registo de que expressões foram geradas, nem telemetria sobre que predefinições são populares, nem maneira de alguém reconstruir o horário em que estava a trabalhar. Expressões cron não são dados pessoais à primeira vista, mas o horário de uma tarefa (uma exportação noturna de base de dados, uma execução semanal de faturação, uma sincronização horária com um parceiro) pode revelar muito sobre como um negócio opera. Manter essa informação do lado do cliente evita vazar acidentalmente padrões de infraestrutura a terceiros. Para uma tarefa tão rotineira como escolher um horário, o nível de privacidade por defeito deve corresponder à sensibilidade do que esses horários representam.
Perguntas frequentes
Qual é o formato da expressão cron?
Uma expressão cron padrão tem 5 campos separados por espaços, representando minuto (0-59), hora (0-23), dia do mês (1-31), mês (1-12) e dia da semana (0-6, onde 0 é domingo). Um asterisco (*) significa "cada" valor nesse campo.
O que significa */5 em cron?
A sintaxe */5 significa "a cada 5º". No campo de minuto, */5 significa a cada 5 minutos (0, 5, 10, 15...). No campo de hora, */5 significa a cada 5 horas. Funciona em qualquer campo.
As expressões cron são iguais em todas as plataformas?
O formato de 5 campos é padrão em Linux cron, AWS EventBridge, GitHub Actions e na maioria dos sistemas de agendamento. Algumas plataformas adicionam um sexto campo para segundos ou ano. Verifique a documentação da sua plataforma.
Como agendo algo para o último dia de cada mês?
O cron padrão não tem uma palavra-chave "último dia". Use uma solução alternativa como executar diariamente e verificar a data no seu script, ou use extensões específicas da plataforma (AWS EventBridge suporta L para "último").
Why did my cron job not run at the expected time?
The most common cause is timezone confusion. Server cron usually runs in UTC, not your local time. Other causes include the server being asleep at the scheduled minute, the user crontab not being installed, or PATH/environment differences between your shell and cron's stripped-down environment.
What is the difference between 0 in the day-of-week field and 7?
Both 0 and 7 represent Sunday in classic Vixie cron, which uses 0-6 plus an alias for 7. Some implementations (notably AWS EventBridge) use 1-7 with Sunday as 7 and Monday as 1, so always check your platform's documentation before assuming.