Cron: o agendador de tarefas do Unix
Criado no Bell Labs no início dos anos 1970, o cron é um daemon Unix responsável por executar comandos em horários pré-determinados. Não há interface gráfica, não há serviço de nuvem por trás, não há SDK para instalar. Existe uma tabela de texto, um conjunto de regras simples, e um processo que acorda uma vez por minuto para verificar o que precisa ser executado. Em 2026, essa mesma lógica ainda roda em milhões de servidores.
A primeira versão do cron foi escrita por Ken Thompson para o Version 7 Unix, em 1977. O funcionamento era direto: o daemon acordava a cada minuto, lia um único arquivo de configuração em /etc/lib/crontab, e executava os comandos agendados para aquele momento, sempre como superusuário. Sem suporte a múltiplos usuários, sem extensões de sintaxe. Apenas o essencial.
Ao longo da década seguinte, o cron foi portado para várias distribuições Unix sem grandes mudanças. A virada veio em 1987, quando Paul Vixie, depois de consultar a comunidade Unix sobre o que faltava na ferramenta, publicou uma nova versão do daemon. O Vixie cron adicionou suporte a crontabs individuais por usuário, expandiu a sintaxe de expressões e resolveu problemas acumulados nas implementações anteriores. Em 1992, a versão 3 do Vixie cron foi publicada na lista comp.sources.unix e tornou-se o ancestral comum de praticamente todas as variantes que existem hoje.
Red Hat e SUSE mantêm desde 2007 um fork chamado cronie, que adiciona suporte a PAM e SELinux. Debian e Ubuntu ainda usam o código original de Vixie com patches acumulados. São caminhos diferentes, mas todos derivam do mesmo tronco.
Em 2025, a Open Cron Pattern Specification (OCPS 1.0) foi publicada como uma tentativa de formalizar o dialeto Vixie cron e resolver ambiguidades que ficaram abertas por décadas. É um sinal de que o formato ainda importa o suficiente para merecer uma especificação escrita.
O que o cron faz
O cron é um daemon, um processo que roda em background de forma contínua. Ele não executa uma tarefa específica, ele executa o que o administrador mandar, no horário que o administrador definir.
Casos de uso comuns incluem:
- Backups noturnos de banco de dados
- Geração e envio de relatórios periódicos
- Limpeza de arquivos temporários e logs antigos
- Sincronização de dados entre sistemas
- Renovação automática de certificados SSL
- Monitoramento e healthchecks recorrentes
- Rotação de chaves e tokens
Qualquer coisa que precise acontecer em intervalos regulares, sem que alguém precise estar ali para acionar manualmente, é candidata a virar um cron job.
A estrutura do crontab
As tarefas do cron ficam registradas em arquivos chamados crontabs. Cada linha representa um job e segue um formato fixo:
* * * * * comando_a_executarOs cinco campos antes do comando representam, nessa ordem: minuto, hora, dia do mês, mês e dia da semana. Uma forma de lembrar é pensar da unidade menor para a maior, do detalhe para o contexto.
* * * * * comando
│ │ │ │ │
│ │ │ │ └── dia da semana (0-6, onde 0 = domingo e 6 = sábado)
│ │ │ └──── mês (1-12)
│ │ └────── dia do mês (1-31)
│ └──────── hora (0-23)
└────────── minuto (0-59)O asterisco funciona como wildcard: significa "qualquer valor válido nesse campo". Uma linha com cinco asteriscos antes do comando executaria aquele comando todo minuto, todos os dias, o ano inteiro.
A sintaxe em detalhe
A força do cron está na composição de quatro operadores básicos que podem ser combinados livremente em cada campo.
Valor único
O caso mais simples. Um número inteiro dentro do range permitido.
0 9 * * * /usr/bin/relatorio.shO campo de minuto é 0, o campo de hora é 9, os outros três são wildcard.
Lista
Múltiplos valores separados por vírgula. O job executa quando qualquer valor da lista corresponde ao momento atual.
0 9 * * 1,3,5 /usr/bin/relatorio.shRange
Dois valores separados por hífen, representando um intervalo inclusivo.
0 9-17 * * 1-5 /usr/bin/healthcheck.shStep
Uma barra seguida de um número, que define o passo entre valores. */N significa "a cada N unidades", começando do valor mínimo do campo.
*/15 * * * * /usr/bin/sync.shEquivale a 0,15,30,45 * * * *.
O step pode ser combinado com range:
0 8-18/2 * * * /usr/bin/tarefa.shCombinações
Os operadores podem ser misturados dentro de um mesmo campo:
0,30 9-17 * * 1-5 /usr/bin/tarefa.shOito execuções por dia útil.
Nomes por extenso
Os campos de mês e dia da semana aceitam abreviações em inglês no lugar de números. MON, TUE, WED, THU, FRI, SAT, SUN para dias da semana; JAN a DEC para meses. Isso melhora a legibilidade em expressões com ranges:
0 0 * JAN-MAR 1-5 /usr/bin/relatorio-trimestral.shGerenciando crontabs
Para editar os jobs do usuário atual, o comando é:
crontab -eIsso abre o crontab no editor definido pela variável $EDITOR. Para listar os jobs existentes:
crontab -lPara remover todos os jobs do usuário:
crontab -rO crontab do sistema fica em /etc/crontab e em arquivos dentro de /etc/cron.d/. Diferente dos crontabs de usuário, esses arquivos têm um sexto campo entre a expressão e o comando, indicando qual usuário deve executar o job:
0 2 * * * root /usr/bin/backup.shTambém existem os diretórios /etc/cron.hourly, /etc/cron.daily, /etc/cron.weekly e /etc/cron.monthly. Scripts colocados nesses diretórios são executados automaticamente nos intervalos correspondentes pelo daemon, sem precisar escrever uma expressão manualmente.
Variáveis de ambiente no crontab
O ambiente em que o cron executa os comandos não é o mesmo do shell interativo. Variáveis como PATH, HOME e SHELL têm valores padrão mínimos, o que é causa frequente de falhas silenciosas quando um script funciona na linha de comando mas não no cron.
É possível definir variáveis diretamente no crontab, antes das linhas de jobs:
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
MAILTO=[email protected]
0 2 * * * /usr/local/bin/backup.shA variável MAILTO define para qual endereço o cron envia a saída dos jobs. Se estiver vazia (MAILTO=""), nenhum e-mail é enviado. Isso é importante: por padrão, o cron tenta enviar um e-mail com qualquer saída gerada pelo job, o que pode encher a fila de mensagens local se o script gerar output com frequência.
Uma prática comum é redirecionar a saída para um arquivo de log ou para /dev/null:
# Ignora stdout e stderr
0 2 * * * /usr/local/bin/backup.sh > /dev/null 2>&1
# Salva stdout e stderr em um log
0 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1A armadilha do dia do mês com dia da semana
Um detalhe de comportamento que gera confusão: quando tanto o campo dia do mês quanto o campo dia da semana estão definidos com valores específicos (nenhum dos dois é wildcard), o Vixie cron os trata com semântica OR. O job executa se qualquer uma das condições for satisfeita, não se ambas forem verdadeiras ao mesmo tempo.
Por exemplo:
0 0 1 * 1 /usr/bin/tarefa.shEssa expressão executa à meia-noite no dia 1 de cada mês e também toda segunda-feira, não apenas nas segundas-feiras que caem no dia 1. Se a intenção era executar só nas segundas que fossem dia 1, o cron padrão não resolve diretamente. A solução convencional é usar um wildcard em um dos campos e colocar a lógica restante dentro do próprio script:
0 0 1 * * [ $(date +%u) -eq 1 ] && /usr/bin/tarefa.shVale mencionar que o Quartz, o scheduler popular no ecossistema Java, usa semântica AND para esses campos e exige que um deles receba ? quando o outro estiver definido. São comportamentos incompatíveis, e trocar de implementação sem atenção a esse detalhe quebra agendamentos silenciosamente.
Limitações conhecidas
O cron é confiável para o que se propõe, mas tem limitações que valem ser conhecidas antes de depender dele em contextos críticos.
A ausência de feedback é a mais significativa. Quando um job falha, o cron não avisa por padrão, a não ser que o sistema de e-mail local esteja configurado e o MAILTO esteja definido. Um backup que retorna erro à meia-noite pode passar despercebido por semanas.
Outra limitação é a granularidade mínima de um minuto. Expressões com precisão de segundos não são suportadas na sintaxe padrão. Para tarefas que precisam rodar a cada 10 segundos, por exemplo, é necessário recorrer a scripts com sleep ou usar uma solução diferente.
O cron também não tem noção de dependência entre jobs. Se a tarefa A precisa ter terminado antes de B começar, isso precisa ser gerenciado externamente.
Por fim, em sistemas que ficam offline periodicamente, um job agendado durante o período de downtime simplesmente não roda. Para isso existe o anacron, que mantém registro das últimas execuções e garante que jobs com intervalos em dias sejam rodados assim que o sistema voltar, mesmo que fora do horário previsto.
Ferramentas para facilitar o trabalho
Escrever e entender expressões cron ficou mais fácil com a disponibilidade de editores visuais, para quem quer algo com visualização campo a campo e exibição das próximas datas de execução, o Cron Editor no ASCII Tools oferece um timeline visual de quais valores estão ativos em cada campo, além de validação por campo com mensagens de erro e presets para as expressões mais comuns.
Referências
- Wikipedia. cron: https://en.wikipedia.org/wiki/Cron
- Kazanov, Vladimir. Cron in Linux: history, use and design. Bumble Tech / Medium, 2020: https://medium.com/bumble-tech/cron-in-linux-history-use-and-structure-70d938569b40
- DEV Community / CronMonitor. The History of Cron: From Unix Daemon to Modern Monitoring Tools, 2025: https://dev.to/cronmonitor/the-history-of-cron-from-unix-daemon-to-modern-monitoring-tools-9io
- Open Cron Pattern Specification. OCPS GitHub Repository, 2025: https://github.com/open-source-cron/ocps
- Ubuntu Manpages. cron(8): https://manpages.ubuntu.com/manpages/trusty/man8/cron.8.html
- The cPanel Admin. Everything You Wanted to Know About Cron: https://www.thecpaneladmin.com/everything-you-wanted-to-know-about-cron/
- Gentoo Wiki. Cron: https://wiki.gentoo.org/wiki/Cron




