Voltar ao blog

Cron vs timers do systemd: qual usar?

11 de setembro de 2026

Numa distro moderna, use um timer do systemd para qualquer coisa que você administra e guarde o cron para jobs de uma linha e servidores que você mesmo não configurou. Timers logam cada execução no journal, podem recuperar agendamentos perdidos com a máquina desligada e dependem dos mesmos unit files que todo o resto do sistema. O cron vence na brevidade — uma linha de crontab -e ganha de dois unit files — e ainda é o único agendador com presença garantida em containers mínimos e máquinas Unix exóticas. A pegadinha: o cron falha em silêncio. Se seu job erra às 3 da manhã, o cron manda um e-mail para uma caixa local que ninguém lê, enquanto o timer te dá journalctl -u mytimer.service com o output completo. Abaixo: as diferenças reais, como testar cada um, por que um timer pode não disparar e uma tabela de decisão.

Qual é a diferença entre cron e um timer do systemd?

O cron é um daemon que lê uma tabela de linhas — cinco campos de tempo e um comando — e roda cada comando quando o relógio bate. Esse é o modelo inteiro. Ele não tem conceito de job como objeto: sem unidade, sem status, sem dependências, sem log próprio.

Um timer do systemd é um unit file (foo.timer) que dispara outro unit file (foo.service) quando o agendamento bate. O job é um objeto de primeira classe, com start, status, logs e rastreio de falha como qualquer serviço. O agendamento é por calendário (estilo cron) ou monotônico (OnBootSec=15min, que mudanças de relógio não confundem).

As consequências práticas:

  • Logging: timers logam stdout/stderr no journal por unidade; o cron, no máximo, manda e-mail para o usuário local.
  • Execuções perdidas: um timer com Persistent=true roda uma vez no boot se perdeu o horário; o cron simplesmente pula.
  • Dependências: timers podem esperar network-online.target ou pontos de montagem; o cron exige retry caseiro no script.
  • Sintaxe: cron é uma linha; timer são dois arquivos. Esse é todo o custo da troca.

Qual sintaxe de agendamento é mais fácil — crontab ou OnCalendar?

Os cinco campos do cron são o incumbente compacto: */15 * * * * é a cada 15 minutos, e a maioria dos admins lê isso dormindo. O OnCalendar= do systemd é mais verboso, mas estritamente mais expressivo, e o systemd-analyze calendar te diz as próximas execuções antes de você salvar — o cron não tem dry-run equivalente.

# Cron: todo dia às 03:30
30 3 * * * /usr/local/bin/backup.sh

# systemd: o mesmo agendamento, verificável antes de salvar
systemd-analyze calendar "*-*-* 03:30:00"
# -> Next elapse: Fri 2026-09-11 03:30:00 ...

O OnCalendar expressa coisas que o cron genuinamente não sabe escrever limpo: Mon..Fri *-*-* 09..17:00:00 (dias úteis, horário comercial), ou *:0/15 com RandomizedDelaySec=10m para impedir mil máquinas de martelarem um servidor no mesmo instante.

Como testar um timer do systemd sem esperar?

Três comandos respondem tudo. Liste o que está agendado e quando dispara de novo, rode o job na mão exatamente como o timer faria, depois leia os logs:

systemctl list-timers --all                 # todos os timers, próxima + última execução
sudo systemctl start backup.service         # dispara o job agora, a mesma unidade que o timer
journalctl -u backup.service -f             # acompanhe o output ao vivo

Note a separação: systemctl start backup.timer arma o agendamento; o serviço é o job. Se o list-timers mostra seu timer, o systemctl status backup.service está verde e o journal mostra seu output, a cadeia inteira funciona.

Como rodar um job do cron manualmente?

Jobs do cron rodam com um ambiente esvaziado, e é por isso que “funciona no meu shell, falha no cron” é um gênero de bug. Para reproduzir o cron com fé, rode o comando via sh com o mesmo ambiente que o cron usaria:

crontab -l                                  # confirme a linha exata
env -i SHELL=/bin/sh PATH=/usr/bin:/bin sh -c '/usr/local/bin/backup.sh'
grep CRON /var/log/syslog | tail            # será que o cron disparou? (Debian/Ubuntu)
journalctl -u cron -n 20                    # o mesmo, em distros systemd

Aquela linha do env -i é o teste manual honesto: um ambiente nu com o PATH default do cron. A maioria das falhas silenciosas do cron é um PATH nu ou um % sem aspas no comando (o cron trata % como newline), e ambos aparecem na hora desse jeito.

Por que meu timer do systemd não dispara?

Quatro causas cobrem quase todo caso, na ordem de verificação:

  1. Nomes do serviço e do timer não batem. foo.timer dispara foo.service — um OnFailure errado na digitação ou uma unidade renomeada faz o timer “rodar” para o nada. systemctl cat foo.timer mostra exatamente o que ele mira.
  2. O timer foi editado mas não recarregado. Depois de mudar um unit file: sudo systemctl daemon-reload && sudo systemctl restart foo.timer. Sem isso, seu novo agendamento não está vivo.
  3. Persistent=true sem a semântica de OnCalendar que você espera — ou você está olhando o systemctl status foo.timer (sempre mostra active, mesmo ocioso) em vez do list-timers.
  4. O serviço que ele dispara está falhando instantaneamente, então o timer parece morto. journalctl -u foo.service --since -1h mostra o crash que o list-timers esconde.

E quando for olhar os logs, o journalctl cheat sheet cobre os filtros (-u, --since, -f) que tornam isso rápido.

Cron vs timers do systemd: a tabela de decisão

crontimer do systemd
Setupuma linha de crontabdois unit files
Logginge-mail local, geralmente não lidojournal, por unidade
Execução perdida (máquina off)puladaroda uma vez com Persistent=true
Dependências / ordenaçãonenhuma — DIY no scriptdependências completas de unidade
Atraso aleatórioDIY com $RANDOMRandomizedDelaySec=
Testar/dry-run do agendamentonãosystemd-analyze calendar
Existe em todo lugarsim — containers, BSDs, embeddedprecisa de systemd (PID 1)
Jobs de usuário sem rootcrontab -eunidades systemd --user

Regras de bolso: entregar um job na sua própria máquina com systemd → timer. Lembrete pessoal rápido ou uma máquina que você não montou → cron. Qualquer coisa com dependências, retries ou necessidade de saber se rodou de fato → timer, sempre. Um padrão comum é um timer rodando um job de manutenção — digamos, um backup com rsync noturno — em que Persistent=true garante que o backup acontece mesmo se a máquina estava dormindo no minuto agendado, coisa que o cron simplesmente não oferece.

— mrsaynothing

Get the next one by email

One email per post. No spam, no algorithms.

self-hosted · no third parties · one-click unsubscribe

what is this?

llama.cpp vs Ollama: qual rodar em 2026?

Gostou dos artigos? É assim que eu construo profissionalmente. me contrate