De acordo com as Leis 12.965/2014 e 13.709/2018, que regulam o uso da Internet e o tratamento de dados pessoais no Brasil, ao me inscrever na newsletter do portal DICAS-L, autorizo o envio de notificações por e-mail ou outros meios e declaro estar ciente e concordar com seus Termos de Uso e Política de Privacidade.

Como substituir o cron por systemd timers

Colaboração: Rubens Queiroz de Almeida

Data de Publicação: 06 de agosto de 2026

Durante décadas, o cron foi a ferramenta tradicional para executar tarefas automaticamente em horários determinados no Linux. Ele continua útil, simples e amplamente disponível, mas as distribuições modernas oferecem outra possibilidade: os timers do systemd. Com eles, uma tarefa agendada passa a ser administrada da mesma maneira que os demais serviços do sistema, com registros centralizados, dependências, controle de recursos, tratamento de falhas e comandos padronizados de gerenciamento.

Substituir uma entrada do cron por um timer exige a criação de duas unidades. A primeira descreve o serviço que será executado. A segunda determina quando esse serviço deverá ser acionado. Essa separação pode parecer mais trabalhosa no começo, porém torna a configuração mais legível, verificável e fácil de diagnosticar.

Por que usar systemd timers?

Uma entrada do cron é compacta e eficiente, mas nem sempre oferece informações suficientes quando algo dá errado. O ambiente disponível para o comando pode ser diferente daquele encontrado no terminal, mensagens de erro podem passar despercebidas e o computador pode estar desligado no momento programado.

Os timers do systemd oferecem algumas vantagens importantes:

  • registros de execução acessíveis pelo journalctl;
  • possibilidade de executar uma tarefa que foi perdida enquanto o computador estava desligado;
  • dependências entre serviços;
  • controle de usuário, grupo, diretório e variáveis de ambiente;
  • limites de memória e processador;
  • opções de isolamento e segurança;
  • expressões de calendário legíveis;
  • execução baseada tanto no relógio quanto em intervalos;
  • ferramentas para verificar antecipadamente os próximos horários de execução.

O systemd não torna o cron obsoleto em todas as situações. Para tarefas simples, uma única linha no crontab pode continuar sendo a solução mais conveniente. Os timers tornam-se especialmente interessantes quando a tarefa precisa de registros detalhados, controle de falhas, dependências ou maior integração com o restante do sistema.

Como funciona um timer?

Um timer geralmente está associado a um serviço de mesmo nome. Considere os arquivos relatorio-disco.service e relatorio-disco.timer.

Quando o timer relatorio-disco.timer chega ao horário programado, o systemd procura e inicia automaticamente o serviço relatorio-disco.service.

O arquivo .service responde à pergunta: O que deverá ser executado?

O arquivo .timer responde: Quando deverá ser executado?

Essa divisão permite testar o serviço manualmente antes de ativar o agendamento.

Exemplo: registrar diariamente o espaço em disco

Nosso exemplo executará o comando df -h todos os dias às 8 horas. A saída será guardada automaticamente no journal do systemd, dispensando a criação e o gerenciamento manual de um arquivo de log.

Criando o serviço

Crie o arquivo:

$ sudo systemctl edit --force --full relatorio-disco.service

Insira o seguinte conteúdo:

[Unit]
Description=Gera um relatório sobre a utilização dos discos

[Service]
Type=oneshot
ExecStart=/usr/bin/df -h

Salve o arquivo e feche o editor.

A opção Type=oneshot indica que o comando realiza uma tarefa e termina. Esse tipo é apropriado para backups, relatórios, atualizações, sincronizações e outras operações de curta duração.

É recomendável informar o caminho completo do programa em ExecStart. Podemos descobrir esse caminho com:

command -v df

Em muitas distribuições, o resultado será /usr/bin/df, mas vale a pena verificar.

Testando o serviço

Antes de criar o agendamento, execute o serviço manualmente:

$ sudo systemctl start relatorio-disco.service

Consulte seu estado:

$ systemctl status relatorio-disco.service

Como o serviço executa uma única tarefa e termina, é normal que seu estado seja exibido como inactive (dead) depois da conclusão. O importante é verificar se a execução foi concluída com sucesso.

Para consultar a saída produzida pelo comando:

$ journalctl -u relatorio-disco.service

Para mostrar somente os registros da execução mais recente:

$ journalctl -u relatorio-disco.service -n 20

Podemos ainda acompanhar uma execução em tempo real:

$ journalctl -fu relatorio-disco.service

Em outro terminal, execute:

$ sudo systemctl start relatorio-disco.service

Criando o timer

Agora crie a unidade que determinará o horário:

$ sudo systemctl edit --force --full relatorio-disco.timer

Insira:

[Unit]
Description=Executa diariamente o relatório de utilização dos discos

[Timer]
OnCalendar=*-*-* 08:00:00
Persistent=true

[Install]
WantedBy=timers.target

A expressão:

OnCalendar=*-*-* 08:00:00

significa que o serviço deverá ser executado todos os anos, em todos os meses e em todos os dias, às 8 horas.

A diretiva:

Persistent=true

faz com que o systemd verifique se alguma execução foi perdida enquanto o computador estava desligado. Se isso tiver ocorrido, o serviço será iniciado depois que o sistema voltar a funcionar.

Esse comportamento é particularmente útil em computadores pessoais. Se uma tarefa estiver programada para as 8 horas, mas o computador for ligado somente às 10 horas, ela ainda poderá ser executada. Em uma configuração convencional do cron, a execução normalmente seria simplesmente perdida.

Ativando o timer

Depois de criar ou alterar unidades, peça ao systemd que releia suas configurações:

$ sudo systemctl daemon-reload

Ative o timer e faça com que ele seja iniciado imediatamente:

$ sudo systemctl enable --now relatorio-disco.timer

Observe que ativamos o arquivo .timer, e não o .service. O serviço será iniciado automaticamente quando o timer chegar ao horário determinado.

Consulte o estado:

$ systemctl status relatorio-disco.timer

Para verificar todos os timers ativos:

$ systemctl list-timers

Para mostrar também os timers inativos:

$ systemctl list-timers --all

A listagem informa quando cada timer foi executado pela última vez e quando ocorrerá a próxima execução.

Verificando uma expressão antes de utilizá-la

Expressões de calendário podem ser testadas com systemd-analyze calendar. Para verificar o horário utilizado no exemplo:

$ systemd-analyze calendar '*-*-* 08:00:00'

O comando apresenta a interpretação da expressão e a próxima ocorrência calculada.

Também é possível solicitar várias ocorrências futuras:

$ systemd-analyze calendar --iterations=5 '*-*-* 08:00:00'

Essa verificação ajuda a evitar erros de configuração, principalmente em expressões semanais ou mensais.

Convertendo expressões do cron

Uma tarefa diária às 8 horas seria representada no cron desta forma:

0 8 * * * /usr/bin/df -h

No timer, usamos:

OnCalendar=*-*-* 08:00:00

Algumas conversões comuns são mostradas a seguir:

Frequência Cron systemd timer
Todos os dias às 8h 0 8 * * * OnCalendar=*-*-* 08:00:00
Todos os dias à meia-noite 0 0 * * * OnCalendar=daily
A cada hora 0 * * * * OnCalendar=hourly
Segunda-feira às 9h 0 9 * * 1 OnCalendar=Mon *-*-* 09:00:00
De segunda a sexta às 18h 0 18 * * 1-5 OnCalendar=Mon..Fri *-*-* 18:00:00
Primeiro dia do mês às 7h 0 7 1 * * OnCalendar=*-*-01 07:00:00
Domingos às 3h30 30 3 * * 0 OnCalendar=Sun *-*-* 03:30:00
A cada 15 minutos */15 * * * * OnCalendar=*:0/15

As palavras hourly, daily, weekly, monthly, quarterly, semiannually e yearly podem ser utilizadas como atalhos em várias configurações.

Antes de empregar qualquer expressão, teste-a:

$ systemd-analyze calendar 'Mon..Fri *-*-* 18:00:00'

Timers baseados em intervalos

Nem todo agendamento precisa estar ligado a um horário específico. Podemos executar uma tarefa determinado tempo depois da inicialização do computador:

[Timer]
OnBootSec=10min

Nesse caso, o serviço será iniciado dez minutos depois do boot.

Também podemos criar uma execução periódica:

[Timer]
OnBootSec=5min
OnUnitActiveSec=1h

Essa configuração inicia a tarefa cinco minutos depois do boot e repete sua execução uma hora depois de cada ativação anterior.

Algumas diretivas importantes são:

Diretiva Significado
OnBootSec= Tempo transcorrido desde a inicialização
OnStartupSec= Tempo transcorrido desde o início do gerenciador systemd
OnActiveSec= Tempo desde a ativação do próprio timer
OnUnitActiveSec= Tempo desde a última ativação da unidade
OnUnitInactiveSec= Tempo desde que a unidade ficou inativa
OnCalendar= Horário definido pelo calendário

As diretivas podem ser combinadas. Se mais de uma condição for especificada, o timer será acionado sempre que qualquer uma delas for satisfeita.

Evitando que vários computadores executem a tarefa ao mesmo tempo

Em servidores, pode ser inconveniente que centenas de máquinas iniciem uma atualização ou sincronização exatamente no mesmo segundo. A diretiva RandomizedDelaySec adiciona um atraso aleatório:

[Timer]
OnCalendar=hourly
RandomizedDelaySec=10min

A tarefa será executada uma vez por hora, mas poderá sofrer um atraso aleatório de até dez minutos. Isso ajuda a distribuir a carga sobre servidores, repositórios e redes.

Para uma tarefa local que precise começar em um horário exato, essa diretiva pode ser omitida.

Executando a tarefa como um usuário específico

Serviços instalados em /etc/systemd/system são administrados pelo systemd do sistema e normalmente são executados como root. Quando a tarefa não precisa de privilégios administrativos, podemos indicar outro usuário:

[Service]
Type=oneshot
User=rubens
Group=rubens
ExecStart=/usr/local/bin/minha-tarefa

Também podemos definir o diretório de trabalho:

WorkingDirectory=/home/rubens

E variáveis de ambiente:

Environment="MODO=producao"
Environment="IDIOMA=pt_BR"

Os nomes de usuário, diretórios e programas devem ser adaptados ao sistema utilizado.

Criando um timer do usuário

Também é possível criar timers que pertencem ao próprio usuário. Nesse caso, não é necessário modificar /etc/systemd/system nem utilizar sudo.

Crie os arquivos dentro de ~/.config/systemd/user/

Por exemplo:

~/.config/systemd/user/relatorio-disco.service
~/.config/systemd/user/relatorio-disco.timer

Depois de salvá-los, execute:

$ systemctl --user daemon-reload
systemctl --user enable --now relatorio-disco.timer

Para consultar os timers do usuário:

$ systemctl --user list-timers

E para examinar os registros:

$ journalctl --user -u relatorio-disco.service

Por padrão, os serviços do usuário normalmente funcionam enquanto sua sessão está ativa. Para permitir que permaneçam disponíveis sem uma sessão aberta, um administrador pode habilitar o chamado *linger*:

$ sudo loginctl enable-linger rubens

Esse recurso deve ser ativado apenas quando houver necessidade de manter serviços do usuário funcionando depois do logout.

Comandos de administração

Os principais comandos utilizados para administrar o timer são:

$ sudo systemctl start relatorio-disco.timer
$ sudo systemctl stop relatorio-disco.timer
$ sudo systemctl restart relatorio-disco.timer
$ sudo systemctl enable relatorio-disco.timer
$ sudo systemctl disable relatorio-disco.timer
$ sudo systemctl enable --now relatorio-disco.timer

Para executar imediatamente a tarefa, sem esperar pelo timer:

$ sudo systemctl start relatorio-disco.service

Para verificar a configuração dos arquivos:

$ systemd-analyze verify /etc/systemd/system/relatorio-disco.service
$ systemd-analyze verify /etc/systemd/system/relatorio-disco.timer

Para mostrar o conteúdo que o systemd efetivamente carregou:

$ systemctl cat relatorio-disco.service
systemctl cat relatorio-disco.timer

Removendo o timer

Primeiro, desative e interrompa o timer:

$ sudo systemctl disable --now relatorio-disco.timer

Remova as duas unidades:

$ sudo rm /etc/systemd/system/relatorio-disco.timer
$ sudo rm /etc/systemd/system/relatorio-disco.service

Finalmente, atualize o systemd:

$ sudo systemctl daemon-reload
$ sudo systemctl reset-failed

Antes de remover qualquer arquivo, confirme os caminhos e os nomes das unidades com systemctl cat.

Problemas frequentes

O timer está ativo, mas o serviço não foi executado

Consulte o timer:

$ systemctl status relatorio-disco.timer

Depois, examine o serviço:

$ systemctl status relatorio-disco.service
$ journalctl -u relatorio-disco.service

O timer apenas determina quando a unidade será acionada. Os detalhes de uma falha estarão geralmente associados ao serviço.

O comando funciona no terminal, mas falha no serviço

Serviços systemd não recebem necessariamente o mesmo ambiente da sessão interativa. Utilize caminhos completos para programas e arquivos:

ExecStart=/usr/local/bin/meu-script

Defina explicitamente o diretório de trabalho e as variáveis necessárias.

O timer não aparece na listagem

Recarregue as unidades:

$ sudo systemctl daemon-reload

Depois, verifique o arquivo:

$ systemd-analyze verify /etc/systemd/system/relatorio-disco.timer

O serviço aparece como inativo depois da execução

Para um serviço Type=oneshot, isso geralmente é normal. Ele executa a tarefa e termina. Consulte o código de saída e os registros para confirmar o resultado:

$ systemctl status relatorio-disco.service
$ journalctl -u relatorio-disco.service

Vale a pena abandonar o cron?

Não existe necessidade de converter imediatamente todas as entradas do crontab. O cron continua adequado para tarefas pequenas, estáveis e simples. Os timers do systemd são particularmente vantajosos quando queremos observar as execuções, guardar registros, aplicar limites, controlar dependências ou recuperar tarefas perdidas durante o desligamento da máquina.

A melhor forma de aprender é começar com uma tarefa pouco crítica, criar o serviço, testá-lo manualmente e somente depois ativar o timer. Essa ordem facilita o diagnóstico porque separa dois problemas diferentes: a execução da tarefa e seu agendamento.

Os timers representam uma abordagem moderna para uma necessidade antiga. Eles integram as tarefas periódicas ao sistema de gerenciamento de serviços do Linux e oferecem ao administrador ferramentas muito mais completas para saber o que foi executado, quando foi executado e por que uma operação eventualmente falhou.

A sintaxe completa das unidades e das expressões de calendário pode ser consultada nas páginas oficiais de systemd.timer e systemd.time.



Veja a relação completa dos artigos de Rubens Queiroz de Almeida