Como Criar e Gerenciar Unidades de Timer do Systemd

Crie, habilite, monitore e solucione problemas de unidades de timer do systemd com exemplos práticos de `.timer`, `.service`, `systemctl` e `journalctl`.

Como Criar e Gerenciar Unidades de Timer do Systemd

As unidades de timer do Systemd agendam tarefas no Linux sem depender do cron. Se você precisa que seu servidor execute um backup, tarefa de limpeza, verificação de integridade ou relatório em um horário previsível, um timer do systemd oferece agendamento, isolamento de serviço, gerenciamento de dependências e logs em um só lugar.

A ideia principal é simples: o arquivo .timer define quando executar, e o arquivo .service define o que executar. Essa separação torna os timers fáceis de inspecionar com systemctl e fáceis de depurar com journalctl.

Entendendo a Estrutura da Unidade de Timer do Systemd

Uma unidade de timer do systemd é sempre emparelhada com uma unidade de serviço correspondente (ou outro tipo de unidade) que ela deve ativar. A unidade de timer define quando a unidade associada deve ser ativada, enquanto a unidade de serviço define qual ação executar. Ambas as unidades geralmente residem no mesmo diretório, geralmente /etc/systemd/system/ para unidades personalizadas.

Um arquivo de unidade de timer típico tem a extensão .timer, e seu arquivo de unidade de serviço associado tem a extensão .service. Por exemplo, se você deseja agendar uma tarefa definida em mytask.service, você criaria um arquivo mytask.timer.

Exemplo: mytask.timer

[Unit]
Description=Executar minha tarefa personalizada diariamente

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Vamos detalhar as seções principais:

  • Seção [Unit]:

    • Description: Uma descrição legível por humanos do timer. Isso é útil para identificação nas saídas de status.
  • Seção [Timer]: Este é o núcleo da unidade de timer, definindo o agendamento.

    • OnCalendar=daily: Esta diretiva especifica quando o timer deve ativar. daily é uma abreviação para meia-noite de cada dia. Outros exemplos incluem:
      • hourly: A cada hora.
      • weekly: Toda semana (equivalente a Mon *-*-* 00:00:00).
      • Sun *-*-* 10:00: Todo domingo às 10h.
      • *-*-15 14:30: No dia 15 de cada mês às 14h30.
      • Mon..Fri *-*-* 09:00: Dias úteis às 9h.
    • Persistent=true: Se definido como true, o timer será ativado o mais rápido possível se o evento ocorreu enquanto o sistema estava desligado. Para timers OnCalendar, isso significa que se o sistema estava desligado durante o horário agendado, o timer será acionado assim que o sistema inicializar e o timer se tornar ativo.
    • OnBootSec=: Ativa o timer um tempo especificado após a inicialização do sistema. Por exemplo, OnBootSec=15min acionaria 15 minutos após a inicialização.
    • OnUnitActiveSec=: Ativa o timer um tempo especificado após a unidade que ele ativa se tornar ativa pela última vez. Por exemplo, OnUnitActiveSec=1h agenda outra execução uma hora após o serviço associado ter sido ativado pela última vez.
    • OnUnitInactiveSec=: Ativa o timer um tempo especificado após a unidade que ele ativa se tornar inativa pela última vez.
    • AccuracySec=: Especifica a precisão do timer. O systemd tenta ativar o sistema para timers apenas se o evento estiver dentro desta janela de tempo, ajudando a economizar energia. O padrão é 1min.
    • RandomizedDelaySec=: Adiciona um atraso aleatório ao acionamento do timer, até a duração especificada. Útil para distribuir a carga.
  • Seção [Install]: Esta seção define como a unidade de timer pode ser habilitada.

    • WantedBy=timers.target: Esta diretiva garante que quando o timer é habilitado, ele se torna parte do timers.target, que é um alvo padrão que inclui todos os timers ativos. Isso significa que o timer será iniciado automaticamente na inicialização, uma vez habilitado.

Exemplo: mytask.service

[Unit]
Description=Serviço de tarefa personalizada

[Service]
Type=oneshot
ExecStart=/usr/local/bin/my_custom_script.sh
User=myuser
Group=mygroup

[Install]
WantedBy=multi-user.target
  • Seção [Unit]:

    • Description: Uma descrição do serviço.
  • Seção [Service]: Isso define o serviço em si.

    • Type=oneshot: Adequado para tarefas que são executadas uma vez e depois saem. Outros tipos existem para daemons de longa duração.
    • ExecStart: O comando a ser executado. Certifique-se de que o script tenha permissões de execução.
    • User/Group: Especifica o usuário e o grupo sob os quais o comando deve ser executado. É uma boa prática não executar tarefas como root, a menos que seja absolutamente necessário.
  • Seção [Install]: Esta seção geralmente não é necessária para um serviço oneshot que deve ser iniciado apenas por um timer. Habilite o timer, não o serviço.

Criando e Habilitando Unidades de Timer

Siga estes passos para criar e gerenciar suas unidades de timer do systemd:

  1. Crie o Arquivo da Unidade de Serviço: Defina sua tarefa em um arquivo .service. Coloque-o em /etc/systemd/system/ (ou ~/.config/systemd/user/ para timers específicos do usuário).

    sudo nano /etc/systemd/system/mytask.service
    

    Cole o conteúdo de exemplo do serviço acima e salve.

  2. Crie o Arquivo da Unidade de Timer: Defina o agendamento em um arquivo .timer correspondente. Coloque-o no mesmo diretório que o arquivo de serviço.

    sudo nano /etc/systemd/system/mytask.timer
    

    Cole o conteúdo de exemplo do timer acima e salve.

  3. Recarregue o Daemon do Systemd: Após criar ou modificar arquivos de unidade, você precisa informar ao systemd para recarregar sua configuração.

    sudo systemctl daemon-reload
    
  4. Habilite o Timer: Para fazer o timer iniciar automaticamente na inicialização, habilite-o.

    sudo systemctl enable mytask.timer
    

    Nota: Você NÃO habilita o arquivo de serviço se ele for destinado apenas a ser acionado pelo timer.

  5. Inicie o Timer: Inicie o timer imediatamente. Ele então será executado de acordo com seu agendamento.

    sudo systemctl start mytask.timer
    

Gerenciando e Monitorando Unidades de Timer

O systemd fornece vários comandos systemctl para gerenciar e monitorar seus timers:

  • Listar todos os timers: Veja todos os timers ativos e inativos.

    systemctl list-timers
    

    Este comando fornece uma saída como:

    NEXT                        LEFT        LAST        PASSED      UNIT          ACTIVATES
    Tue 2023-10-27 08:00:00 UTC 10h left    Wed 2023-10-26 08:00:00 UTC 14h ago       mytask.timer  mytask.service
    

    Isso mostra quando o timer está programado para ser executado em seguida, quanto tempo falta para ser executado, quando foi executado pela última vez e qual serviço ele ativa.

  • Listar timers para uma unidade específica: Se você quiser ver timers relacionados a um serviço específico.

    systemctl list-timers --all | grep mytask.service
    
  • Verificar Status do Timer: Obtenha informações detalhadas sobre um timer específico.

    systemctl status mytask.timer
    

    Isso mostrará se o timer está ativo, quando está programado para ser executado em seguida e entradas de log recentes.

  • Visualizar Logs do Serviço: Para ver a saída e o status da tarefa executada pelo timer, verifique os logs do serviço associado.

    journalctl -u mytask.service
    

    Você também pode acompanhar os logs em tempo real:

    journalctl -f -u mytask.service
    
  • Parar um Timer: Se você precisar desabilitar temporariamente um timer.

    sudo systemctl stop mytask.timer
    
  • Desabilitar um Timer: Para evitar que um timer inicie na inicialização e pará-lo se estiver em execução.

    sudo systemctl disable --now mytask.timer
    

Configurações Avançadas de Timer

Definindo Intervalos Específicos

Em vez de daily ou hourly, você pode definir intervalos mais precisos:

  • A cada N minutos: OnUnitActiveSec=15min (executa 15 minutos após o serviço ter sido ativado pela última vez).
  • Horários específicos: OnCalendar=*-*-* 02:30:00 (executa diariamente às 2h30).
  • Combinando condições: OnCalendar=Mon..Fri *-*-* 08:00:00 (executa em dias úteis às 8h).

Usando AccuracySec para Economia de Energia

Se sua tarefa não precisa ser executada em um momento exato, considere usar AccuracySec. Por exemplo, AccuracySec=5min informa ao systemd que não há problema em ativar o sistema dentro de 5 minutos do horário agendado. Isso permite que o systemd agrupe eventos de timer e potencialmente mantenha o sistema em um estado de energia mais baixo por mais tempo.

[Timer]
OnCalendar=hourly
AccuracySec=5min

Persistent vs. WakeSystem

  • Persistent=true garante que, se um evento OnCalendar for perdido devido ao sistema estar desligado, ele será executado uma vez na próxima inicialização. Isso é crucial para tarefas que não devem ser ignoradas.
  • WakeSystem=true pede ao systemd para ativar o sistema do modo de suspensão para o timer, se o sistema e o hardware suportarem. Não é o mesmo que decidir se a máquina está na energia CA ou na bateria.

Timers vs. Cron

Recurso Timers do Systemd Cron
Integração Integração profunda com serviços do systemd, targets Utilitário independente
Agendamento Flexível (calendário, relativo, baseado em inicialização) Expressões baseadas principalmente em tempo
Registro Centralizado via journalctl Disperso (/var/log/syslog, /var/log/cron.log)
Tratamento de Erros Pode vincular ações a falhas de serviço Notificações básicas por e-mail
Dependências Pode depender de outros serviços estarem ativos Limitado
Execução Pode executar como usuários, grupos específicos Pode executar como usuários específicos via crontab
Gerenciamento de Energia Pode ser otimizado para economia de energia (AccuracySec) Menos controle direto

Quando escolher Timers do Systemd:

  • Quando você precisa de uma integração mais estreita com outros serviços do systemd.
  • Quando o registro centralizado e a depuração mais fácil são prioridades.
  • Quando você precisa de opções de agendamento mais avançadas (por exemplo, tempo desde a última execução).
  • Para tarefas relacionadas ao estado do sistema ou gerenciamento de energia.

Quando o Cron ainda pode ser preferido:

  • Para tarefas muito simples e independentes em sistemas que não adotam totalmente o systemd.
  • Para máxima compatibilidade entre diferentes distribuições Linux e sistemas mais antigos.

Solução de Problemas Comuns

  • Tarefa não está sendo executada:
    • Verifique o status do timer: systemctl status mytask.timer. Procure por mensagens Active: active e Triggered....
    • Verifique os logs do serviço: journalctl -u mytask.service. Certifique-se de que o script é executável e não tem erros.
    • Verifique a sintaxe do OnCalendar: Use systemd-analyze calendar 'sua-string-de-calendario' para testar.
    • Certifique-se de que o timer está habilitado e iniciado: systemctl list-timers --all.
  • Tarefa executa muito cedo/tarde:
    • Verifique AccuracySec e RandomizedDelaySec.
    • Certifique-se de que o relógio do sistema está preciso (timedatectl status).
  • Erros de permissão:
    • Confirme se o User e Group especificados no arquivo .service têm as permissões necessárias para o script e quaisquer arquivos que ele acessa.
    • Se nenhum usuário for especificado, o padrão é root. Tenha cuidado com privilégios de root.

Conclusão

Use um timer do systemd quando o trabalho pertencer à camada de serviço da máquina: backups, tarefas de limpeza, verificações de monitoramento, hooks de renovação de certificados e outros trabalhos operacionais. Crie o serviço primeiro, crie o timer em seguida, execute systemctl daemon-reload, habilite e inicie o timer, depois verifique com systemctl list-timers --all e journalctl -u seu.servico.