Ir para o conteúdoIr para navegação de página: página anterior [tecla de acesso p]/próxima página [tecla de acesso n]
documentation.suse.com / Trabalhando com temporizadores do systemd

Trabalhando com temporizadores do systemd

Data de Publicação: 29/09/2024
O QUE É?

Desde a execução de um script de backup em intervalos regulares até o início de um processo específico logo após a inicialização da máquina, há muitas tarefas que exigem programação em um sistema Linux. Os temporizadores do systemd oferecem um mecanismo flexível para programar e gerenciar tarefas e serviços.

POR QUÊ?

Este artigo apresenta uma visão geral completa dos temporizadores do systemd, abordando a criação, a manutenção, o teste, a solução de problemas e a migração do cron.

DEDICAÇÃO

A criação de um temporizador do systemd de exemplo leva 10 minutos. Pode levar até 30 minutos para entender completamente como funcionam os temporizadores do systemd.

REQUISITOS

1 O conceito de temporizador do systemd

As unidades do temporizador do systemd oferecem um mecanismo para programar tarefas no Linux. O horário de execução dessas tarefas pode ser baseado em horário e data ou em eventos.

As unidades do temporizador do systemd são identificadas pela extensão de nome de arquivo .timer. Cada arquivo de temporizador requer um arquivo de serviço correspondente que ele controla. Em outras palavras, um arquivo de temporizador ativa e gerencia o arquivo de serviço correspondente. Os temporizadores do systemd suportam os seguintes recursos:

  • As tarefas programadas usando uma unidade do temporizador podem depender de outros serviços do systemd. As unidades do temporizador são tratadas como serviços regulares do systemd, portanto, podem ser gerenciadas com o systemctl.

  • Os temporizadores podem ser em tempo real (acionados com base em eventos do calendário) ou monotônicos (acionados em um determinado tempo decorrido a partir de um ponto inicial específico).

  • As unidades de tempo são registradas no diário do sistema, o que facilita seu monitoramento e sua solução de problemas.

  • Os temporizadores usam os serviços de gerenciamento centralizado do systemd.

  • Se o sistema estiver desligado durante o período de execução esperado, o temporizador será executado quando o sistema for ligado novamente.

2 Criando um temporizador

O exemplo a seguir mostra como configurar um temporizador que aciona o script de shell helloworld.sh após o momento da inicialização e repete sua execução a cada 24 horas em relação ao horário de ativação. Ele também é executado de segunda a sexta às 10h.

2.1 Exemplo de Hello World

  1. Crie o arquivo /etc/systemd/system/helloworld.service com o seguinte conteúdo:

    [Unit]
    Description="Hello World script"
    
    [Service]
    ExecStart=/usr/local/bin/helloworld.sh

    Esse é um arquivo de serviço do systemd que informa qual aplicativo o systemd deve executar.

  2. Crie o arquivo /etc/systemd/system/helloworld.timer com o seguinte conteúdo:

    [Unit]
    Description="Run helloworld.service 5min after boot and every 24 hours relative to activation time"
    
    [Timer]
    OnBootSec=5min
    OnUnitActiveSec=24h
    OnCalendar=Mon..Fri *-*-* 10:00:*
    Unit=helloworld.service
    
    [Install]
    WantedBy=multi-user.target

    Esse é o arquivo de temporizador que controla a ativação do respectivo arquivo de serviço.

  3. Verifique se os arquivos criados acima não contêm erros:

    > systemd-analyze verify /etc/systemd/system/helloworld.*

    Se o comando não retornar nenhuma saída, os arquivos foram aprovados na verificação.

  4. Inicie o temporizador:

    > sudo systemctl start helloworld.timer

    Ativa o temporizador apenas para a sessão atual.

  5. Habilite o temporizador para verificar se ele está ativado na inicialização:

    > sudo systemctl enable helloworld.timer

2.2 O exemplo explicado

Exemplo 1: O arquivo de serviço
[Unit]
Description="Hello World script"1

[Service]
ExecStart=/usr/local/bin/helloworld.sh2

1

Uma breve descrição que explica a finalidade do arquivo de serviço.

2

O aplicativo que será executado.

[Unit] e [Service] são as seções mínimas necessárias para que um arquivo de serviço funcione. Os arquivos de serviço do systemd normalmente contêm uma seção [Install] que determina um ou mais destinos para um serviço carregar. Essa seção não é necessária em arquivos de serviço para temporizadores, pois essas informações são fornecidas com o arquivo de temporizador. Para configuração avançada, consulte Managing systemd targets with systemctl.

Exemplo 2: O arquivo de temporizador
[Unit]
Description="Run helloworld.service 5min after boot and every 24 hours relative to activation time"1

[Timer]
OnBootSec=5min2
OnUnitActiveSec=24h3
OnCalendar=Mon..Fri *-*-* 10:00:*4
Unit=helloworld.service5

[Install]
WantedBy=multi-user.target6

1

Uma breve descrição que explica a finalidade do arquivo de temporizador.

2

Especifica um temporizador que aciona o serviço cinco minutos após a inicialização do sistema. Consulte Temporizadores monotônicos para obter os detalhes.

3

Especifica um temporizador que aciona o serviço 24 horas após a ativação do serviço (ou seja, o temporizador aciona o serviço uma vez por dia). Consulte Temporizador em tempo real para obter os detalhes.

4

Especifica um temporizador que aciona o serviço em horários fixos (neste exemplo, de segunda a sexta às 10h). Consulte Temporizador em tempo real para obter os detalhes.

5

O arquivo de serviço que será executado.

6

O destino do systemd no qual o temporizador é ativado. Para obter mais informações sobre destinos do systemd, consulte Managing systemd targets with systemctl.

3 Gerenciando temporizadores

Você pode gerenciar temporizadores usando o comando systemctl.

Iniciando e parando temporizadores
> sudo systemctl start TIMER.timer
> sudo systemctl restart TIMER.timer
> sudo systemctl stop TIMER.timer
Habilitando e desabilitando temporizadores
> sudo systemctl enable TIMER.timer
> sudo systemctl disable TIMER.timer
Mostrando o conteúdo do arquivo de temporizador
> sudo systemctl cat TIMER.timer
Verificando um temporizador específico
> sudo systemctl status TIMER.timer
Exemplo 3: Status do temporizador
> sudo systemctl status helloworld.timer
● helloworld.timer - "Run helloworld.service 5min after boot and every 24 hours
relative to activation time"1
Loaded: loaded (/etc/systemd/system/helloworld.timer; disabled; vendor preset: disabled)2
Active: active (waiting) since Tue 2022-10-26 18:35:41 CEST; 6s ago3
Trigger: Wed 2022-10-27 18:35:41 CEST; 23h left4
Triggers: ● helloworld.service5
6
Oct 26 18:35:41 neo systemd[1]: Started "Run helloworld.service 5min after boot and every 24 hours relative to activation time".7

1

O nome e a descrição do arquivo do temporizador.

2

Lista se um temporizador foi analisado com êxito e mantido na memória (carregado), exibe o caminho completo para o arquivo do temporizador e mostra se o temporizador é iniciado no momento da inicialização (habilitado) ou não (desabilitado). O primeiro valor mostra a configuração atual do sistema, o segundo valor mostra a predefinição do fornecedor.

3

Indica se o temporizador está ativo (aguardando para acionar eventos) ou inativo. Se estiver ativo, ele também mostrará o tempo decorrido desde a última ativação (6 segundos neste exemplo).

4

Data e horário em que o temporizador será acionado da próxima vez.

5

Nome do arquivo de serviço acionado pelo temporizador.

6

Linha opcional que aponta para a documentação (por exemplo, páginas de manual). Se não estiver disponível, uma linha vazia será mostrada (como neste exemplo).

7

Última entrada do diário criada pelo temporizador.

Para listar todos os temporizadores disponíveis no sistema, use o comando systemctl list-timers. As seguintes opções estão disponíveis:

Listar todos os temporizadores ativos:
> sudo systemctl list-timers
Listar todos os temporizadores, incluindo os inativos:
> sudo systemctl list-timers --all
Listar todos os temporizadores que correspondem a um padrão:
> sudo systemctl list-timers PATTERN
> sudo systemctl list-timers --allPATTERN

PATTERN deve ser um nome ou uma expressão globbing do shell. É possível usar os operadores *, ? e []. Consulte man 7 glob para obter mais informações sobre os padrões de globbing.

Listar temporizadores que correspondem a um determinado estado:
> sudo systemctl list-timers --state=STATE

STATE assume os seguintes valores: active, failed, load, sub. Consulte o man systemctl para obter os detalhes.

Exemplo 4: Listando temporizadores

Executar qualquer comando systemctl list-timers resulta na tabela abaixo. Neste exemplo, todos os temporizadores ativos que correspondem ao padrão snapper* são listados:

> sudo systemctl list-timers snapper*
NEXT1                       LEFT2      LAST3                        PASSED4   UNIT5                  ACTIVATES6

-----------------------------------------------------------------------------------------------------------------------------
Tue 2022-10-26 19:00:00 CEST 39min left Tue 2022-10-26 18:00:29 CEST 19min ago snapper-timeline.timer snapper-timeline.service
Wed 2022-10-27 08:33:04 CEST 14h   left Tue 2022-10-26 08:33:04 CEST 9h ago    snapper-cleanup.timer  snapper-cleanup.service

1

O ponto no tempo da próxima execução do temporizador.

2

O tempo restante até a próxima execução do temporizador.

3

O ponto no tempo da última execução do temporizador.

4

Tempo decorrido desde a última execução do temporizador.

5

O nome da unidade do temporizador.

6

O nome do serviço ativado pelo temporizador.

4 Tipos de temporizador

O systemd suporta dois tipos de temporizadores: tempo real (baseado em calendário) e monotônico (baseado em eventos). Os temporizadores costumam ser persistentes, mas o systemd também permite configurar temporizadores temporários que são válidos apenas para a sessão atual.

Temporizador em tempo real

Os temporizadores em tempo real são acionados por eventos do calendário. Eles são definidos por meio da opção OnCalendar.

Você pode especificar quando acionar um evento com base na data e no horário. Use o seguinte modelo:

OnCalendar=DayOfWeek1 Year-Month-Day2 Hour:Minute:Second3

1

Dia da semana. Os valores possíveis são Sun, Mon, Tue, Wed, Thu, Fri e Sat. Deixe vazio para ignorar o dia da semana.

2

Data. Especifique o mês e o dia com dois dígitos e o ano com quatro dígitos. Cada valor pode ser substituído pelo curinga * para corresponder a todas as ocorrências.

3

Horário. Especifique cada valor com dois dígitos. Cada valor pode ser substituído pelo curinga * para corresponder a todas as ocorrências.

Aplica-se a todos os valores: Use dois pontos para definir uma faixa contínua (Mon..Fri). Use uma vírgula para delimitar uma lista de valores separados (Mon,Wed,Fri).

Exemplo 5: Exemplos de temporizador em tempo real
  • 18h todas as sextas:

    OnCalendar=Fri *-*-* 18:00:00
  • 5h todos os dias:

    OnCalendar=Mon..Sun *-*-* 5:00:00
  • 1h e 3h aos domingos e às terças-feiras:

    OnCalendar=Tue,Sun *-*-* 01,03:00:00
  • Data única:

    OnCalendar=Mo..Sun 2023-09-23 00:00:01
  • Para especificar acionadores em horários diferentes, você pode criar mais de uma entrada OnCalendar em um único arquivo de temporizador:

    OnCalendar=Mon..Fri *-*-* 10:00
    OnCalendar=Sat,Sun *-*-* 22:00

Para obter uma lista completa dos recursos e das opções disponíveis, consulte man 7 systemd.time, que oferece informações adicionais sobre os seguintes tópicos:

  • reduzir a sintaxe e usar abreviações

  • especificar repetições

  • encontrar dias específicos em um mês (último dia do mês, último domingo etc.)

  • aplicar fusos horários

Temporizadores monotônicos

Os temporizadores monotônicos são acionados em um determinado tempo decorrido de um evento específico, como inicialização do sistema ou evento de ativação de unidade do sistema. Os valores são definidos como unidades de tempo (minutos, horas, dias, meses, anos etc.). As seguintes unidades são suportadas: usec, msec, seconds, minutes, hours, days, weeks, months, years. Há várias opções para definir temporizadores monotônicos:

  • OnActiveSec: tempo após a ativação da unidade

    OnActiveSec=50minutes
  • OnBootSec: tempo após a inicialização do sistema

    OnBootSec=10hours
  • OnStartupSec: tempo após a inicialização do gerenciador de serviços. Para serviços do sistema, essa configuração é quase igual a OnActiveSec. Use-a para serviços de usuário em que o gerenciador de serviços é iniciado no momento do login do usuário.

    OnStartupSec=5minutes 20seconds
  • OnUnitActiveSec: tempo após a última ativação do serviço correspondente

    OnUnitActiveSec=10seconds
  • OnUnitInactiveSec: tempo após a última desativação do serviço correspondente

    OnUnitInactiveSec=2hours 15minutes 18 seconds
Temporizadores temporários

Trata-se de temporizadores válidos apenas para a sessão atual. Usando esses temporizadores, você pode utilizar um arquivo de serviço existente ou iniciar diretamente um programa. Os temporizadores temporários são chamados ao executar o comando systemd-run.

O exemplo a seguir executa a unidade helloworld.service a cada duas horas:

> sudo systemd-run --on-active="2hours" --unit="helloworld.service"

Para executar um comando diretamente, use a sintaxe a seguir. Neste exemplo, o script /usr/local/bin/helloworld.sh é chamado diretamente:

> sudo systemd-run --on-active="2hours" /usr/local/bin/helloworld.sh

Se o comando usar parâmetros, adicione-os separados por espaço:

> sudo systemd-run --on-active="2hours" /usr/local/bin/helloworld.sh --language=pt_BR

Os temporizadores temporários podem ser monotônicos ou em tempo real. Os switches a seguir são suportados e funcionam conforme descrito em Temporizadores monotônicos:

  • --on-active

  • --on-startup

  • --on-unit-active

  • --on-unit-inactive

  • --on-calendar

Para obter mais informações, consulte man 1 systemd-run.

5 Testando entradas de calendário

O systemd fornece uma ferramenta para testar e criar entradas de temporizador de calendário para temporizadores em tempo real: systemd-analyze calendar. Ela aceita o mesmo argumento que a entrada OnCalendar necessária para configurar temporizadores em tempo real.

Você pode concatenar vários argumentos separados por espaço. Se o termo a ser testado estiver correto, a saída mostrará quando o temporizador será acionado da próxima vez (no horário local e em UTC). Ela também mostrará a string em Normalized form, e é recomendável usar essa string no arquivo do temporizador. Considere estes exemplos:

> systemd-analyze calendar "Tue,Sun *-*-* 01,03:00:00"
Normalized form: Tue,Sun *-*-* 01,03:00:00
Next elapse: Sun 2021-10-31 01:00:00 CEST
(in UTC): Sat 2021-10-30 23:00:00 UTC
From now: 3 days left

> systemd-analyze calendar "Mon..Fri *-*-* 10:00" "Sat,Sun *-*-* 22:00"
Original form: Mon..Fri *-*-* 10:00
Normalized form: Mon..Fri *-*-* 10:00:00
Next elapse: Thu 2021-10-28 10:00:00 CEST
(in UTC): Thu 2021-10-28 08:00:00 UTC
From now: 19h left

Original form: Sat,Sun *-*-* 22:00
Normalized form: Sat,Sun *-*-* 22:00:00
Next elapse: Sat 2021-10-30 22:00:00 CEST
(in UTC): Sat 2021-10-30 20:00:00 UTC
From now: 3 days left

Para temporizadores recorrentes, use o switch –iterations N para listar os horários de acionamento e, em seguida, teste se eles funcionam como esperado. O argumento N especifica o número de iterações que você deseja testar. A string de exemplo a seguir é acionada a cada 8 horas (começando à 00:00:00) aos domingos:

> systemd-analyze calendar --iterations 5 "Sun *-*-* 0/08:00:00"
Original form: Sun *-*-* 0/08:00:00
Normalized form: Sun *-*-* 00/8:00:00
Next elapse: Sun 2021-10-31 00:00:00 CEST
(in UTC): Sat 2021-10-30 22:00:00 UTC
From now: 3 days left
Iter. #2: Sun 2021-10-31 08:00:00 CET
(in UTC): Sun 2021-10-31 07:00:00 UTC
From now: 3 days left
Iter. #3: Sun 2021-10-31 16:00:00 CET
(in UTC): Sun 2021-10-31 15:00:00 UTC
From now: 4 days left
Iter. #4: Sun 2021-11-07 00:00:00 CET
(in UTC): Sat 2021-11-06 23:00:00 UTC
From now: 1 week 3 days left
Iter. #5: Sun 2021-11-07 08:00:00 CET
(in UTC): Sun 2021-11-07 07:00:00 UTC
From now: 1 week 3 days left

6 Recebendo notificações por e-mail quando há falha no temporizador

O systemd não oferece um recurso semelhante ao MAILTO do cron. O procedimento a seguir descreve uma solução alternativa para habilitar notificações por e-mail quando há falha em um temporizador.

O procedimento consiste nas seguintes etapas:

  1. Crie um script para enviar um e-mail.

  2. Crie um arquivo de serviço do systemd com a execução do script de e-mail.

  3. Teste o arquivo de serviço de e-mail.

  4. No serviço controlado pelo temporizador, chame o arquivo de serviço de e-mail criado por meio de OnFailure.

No exemplo a seguir, usamos o comando mailx do pacote mailx. Ele requer a instalação e a configuração correta do servidor de e-mail Postfix.

  1. Crie o script /usr/local/bin/send_systemd_email.

    1. O script requer dois parâmetros: $1, o endereço de e-mail, e $2, o nome do arquivo de serviço no qual a notificação de falha é recebida. Ambos os parâmetros são fornecidos pelo arquivo de unidade que executa o script de e-mail.

      #!/bin/sh
      systemctl status --full "$2" | mailx -S sendwait\
       -s "Service failure for $2" -r root@$HOSTNAME $1
    2. Verifique se o script é executável:

      > sudo chmod 755 /usr/local/bin/send_systemd_email
  2. Crie o arquivo /etc/systemd/system/send_email_to_USER@.service.

    [Unit]
    Description=Send systemd status information by email for %i to USER
    
    [Service]
    Type=oneshot
    ExecStart=/usr/local/bin/send_systemd_email EMAIL_ADDRESS %i
    User=root
    Group=systemd-journal

    Substitua USER e EMAIL_ADDRESS no arquivo pelo login e endereço de e-mail do usuário que deve receber o e-mail. %i é o nome do serviço que falhou (ele é passado para o serviço de e-mail pelo parâmetro %n).

  3. Verifique o arquivo de serviço e corrija os problemas relatados:

    > systemd-analyze verify /etc/systemd/system/send_email_to_USER@.service

    Se o comando não retornar nenhuma saída, o arquivo foi aprovado na verificação.

  4. Para verificar o procedimento completo, inicie o serviço usando a instância dbus para teste. (Você pode usar qualquer outro serviço que esteja em execução. O dbus é usado neste exemplo porque a execução do serviço é garantida em qualquer instalação.)

    > sudo systemctl start send_email_to_USER@dbus.service

    Se for bem-sucedido, EMAIL_ADDRESS receberá um e-mail com o assunto Service failure for dbus contendo mensagens de status do dbus no corpo. (Isso é apenas um teste, não há problema com o serviço dbus. Você pode apagar o e-mail com segurança, nenhuma ação é necessária).

    Se o e-mail de teste for enviado com êxito, continue integrando-o ao arquivo de serviço.

  5. Para adicionar uma notificação por e-mail ao serviço, adicione uma opção OnFailure à seção Unit do arquivo de serviço para a qual você deseja ser notificado em caso de falha:

    [Unit]
    Description="Hello World script"
    OnFailure1=send_email_to_USER2@%n3.service
    
    [Service]
    ExecStart=/usr/local/bin/helloworld.sh

    1

    A opção OnFailure usa um serviço como argumento.

    2

    Substitua a parte do nome de arquivo da unidade de serviço pelo nome de login.

    3

    Especifica o nome do serviço (neste exemplo, helloworld). Esse nome está disponível no arquivo de serviço de e-mail como %i.

  6. Você configurou com êxito a notificação de falha para os serviços do systemd.

Dica
Dica: Enviando notificações por e-mail a vários usuários

O arquivo de serviço de e-mail tem o endereço de e-mail do destinatário codificado. Para enviar e-mails de notificação a um usuário diferente, copie o arquivo de serviço de e-mail e substitua o login do usuário no nome de arquivo e o endereço de e-mail na cópia.

Para enviar uma notificação de falha a vários destinatários simultaneamente, adicione os respectivos arquivos de serviço ao arquivo de serviço (use espaços como separador):

OnFailure=send_email_to_tux@%n.service send_email_to_wilber@%n.service

7 Usando temporizadores como um usuário comum

Os temporizadores do systemd também podem ser usados por usuários comuns. Isso ajuda você a automatizar tarefas recorrentes, como backups, processamento de imagens ou migração de dados para a nuvem.

Os mesmos procedimentos e tarefas dos temporizadores de todo o sistema são válidos. No entanto, as seguintes diferenças se aplicam:

  • Os arquivos de temporizador e de serviço devem ser colocados em ~/.config/systemd/user/.

  • Todos os comandos systemctl e journalctl devem ser executados com o switch ‑‑user. O systemd-analyze não requer essa opção.

    Como usuário comum, você deve indicar o caminho para os arquivos de unidade, como nos exemplos abaixo. Do contrário, se existir um temporizador em todo o sistema com o mesmo nome, ele será executado ou listado.

    > systemctl --user start ~/.config/systemd/user/helloworld.timer
    > systemctl --user enable ~/.config/systemd/user/helloworld.timer
    > systemctl --user list-timers
    > journalctl --user -u helloworld.*
    > systemd-analyze verify ~/.config/systemd/user/helloworld.timer
Importante
Importante: Os temporizadores de usuário são executados apenas durante uma sessão ativa

Assim como em outros serviços do systemd iniciados como usuário comum, os temporizadores de usuário são executados apenas quando o usuário está conectado. Em vez disso, para iniciar os temporizadores do usuário no momento da inicialização e mantê-los em execução após o logout, habilite lingering para cada usuário afetado:

sudo loginctl enable-linger USER

Para obter mais informações, consulte o man 1 loginctl.

Importante
Importante: Variáveis de ambiente não são herdadas

A instância de usuário do systemd não herda variáveis de ambiente definidas por scripts como ~/.profile ou ~/.bashrc. Para verificar o ambiente do systemd, execute systemctl --user show-environment.

Para importar qualquer variável ausente no ambiente do systemd, especifique o seguinte comando no final do arquivo ~/.bashrc:

systemctl --user import-environment VARIABLE1 VARIABLE2

8 Migrando do cron para temporizadores do systemd

Todas as tarefas cron podem ser migradas para temporizadores do systemd. Encontre instruções e um exemplo aqui.

  1. Crie um arquivo de serviço executando o script. Consulte o Exemplo 1, “O arquivo de serviço” para obter os detalhes.

  2. Crie um arquivo de temporizador executando o arquivo de serviço. Consulte o Exemplo 2, “O arquivo de temporizador” para obter instruções gerais.

    1. Converta entradas de calendário. O horário é especificado de forma diferente no cron e no systemd. Use os padrões abaixo como modelo de conversão:

      Cron:               Minute Hour Day Month DayOfWeek
      systemd: OnCalendar=DayOfWeek Year-Month-Day Hour:Minute:Second

      Para testar a entrada de calendário convertida, siga as instruções na Seção 5, “Testando entradas de calendário”.

    2. Converta apelidos do cron (@NICK):

      Cron     : systemd timer
      -------- : ----------------------------
      @reboot  : OnBootSec=1s
      @yearly  : OnCalendar=*-01-01 00:00:00
      @annually: OnCalendar=*-01-01 00:00:00
      @monthly : OnCalendar=*-*-01 00:00:00
      @weekly  : OnCalendar=Sun *-*-* 00:00:00
      @daily   : OnCalendar=*-*-* 00:00:00
      @hourly  : OnCalendar=*-*-* *:00:00
    3. Converta atribuições de variáveis. A atribuição de variável do systemd deve ir para a seção [Service]. Você não pode converter MAILTO dessa forma. Consulte a próxima etapa para isso.

      cron: VARIABLE=VALUE
      systemd: Environment="VARIABLE=VALUE"
    4. Configure notificações por e-mail para substituir o recurso MAILTO do cron seguindo as instruções na Seção 6, “Recebendo notificações por e-mail quando há falha no temporizador”.

Exemplo 6: Migração do temporizador do cron para o systemd

Estas são as entradas do crontab que chamam o script helloworld.sh 5 minutos após a inicialização e às 10 horas de segunda-feira a sexta-feira:

@reboot sleep 300 && /usr/local/bin/helloworld.sh
0 10 * * * 1-5 /usr/local/bin/helloworld.sh

O arquivo de serviço do systemd (helloworld.service) que chama o script tem a seguinte aparência:

[Unit]
Description="Hello World script"
[Service]
ExecStart=/usr/local/bin/helloworld.sh

O arquivo de temporizador (helloworld.timer) tem a seguinte aparência:

[Unit]
Description="Run helloworld.service 5min after boot and at 10am every Mon-Fri"
[Timer]
OnBootSec=5min
OnCalendar=Mon..Fri *-*-* 10:00:*
Unit=helloworld.service
[Install]
WantedBy=multi-user.target

9 Solução de problemas e perguntas frequentes

Saiba como depurar e solucionar problemas de temporizadores do systemd que falharam. Encontre respostas a perguntas frequentes sobre os temporizadores do systemd.

9.1 Evitando erros

Para evitar erros com temporizadores do systemd, siga estas melhores práticas:

  • Verifique se o executável especificado no serviço com ExecStart funciona corretamente.

  • Verifique a sintaxe dos arquivos de serviço e do temporizador executando systemd-analyze verify FILE.

  • Verifique os horários de execução das entradas de calendário executando systemd-analyze calendar CALENDER_ENTRY.

9.2 O evento não é acionado

Quando você ativa um temporizador que contém erros não críticos, o systemd os ignora silenciosamente. Por exemplo:

Exemplo 7: Recorte do arquivo de temporizador do systemd com um erro não fatal
[Timer]
OnBootSec=5min
OnClendar=Mon..Fri 10:00
Unit=helloworld.service

A linha 3 contém um erro de sintaxe (OnClendar em vez de OnCalendar). Como a seção [Timer] contém uma segunda entrada de temporizador (OnBoot), o erro não é crítico e é ignorado silenciosamente. Como consequência, o acionador de segunda a sexta não é executado. A única maneira de detectar o erro é usar o comando systemd-analyze verify:

#  systemd-analyze verify /etc/systemd/system/helloworld.timer
/etc/systemd/system/helloworld.timer:7: Unknown key name 'OnClendar' in section 'Timer', ignoring.

9.3 Verificando se há erros no diário do sistema

Como em todos os serviços do systemd, os eventos e as ações acionados por temporizadores são registrados no diário do sistema. Se um acionador não se comportar como esperado, consulte as mensagens de registro usando o comando journalctl. Para filtrar o diário para obter informações relevantes, use o switch -u para especificar os temporizadores e os arquivos de serviço do systemd. Use esta opção para mostrar as entradas de registro para o temporizador e o arquivo de serviço correspondente:

sudo journalctl -u  helloworld.timer -u helloworld.service

ou uma opção mais curta (se aplicável):

sudo journalctl -u  helloworld.*

journalctl é uma ferramenta que suporta várias opções e filtros. Consulte man 1 journalctl para obter informações completas. As opções a seguir são úteis para solução de problemas de temporizadores:

  • -b: Mostrar apenas entradas para a inicialização atual.

  • -S today: Mostrar apenas entradas de hoje.

  • -x: Mostrar os textos de ajuda ao lado da entrada de registro.

  • -f: Começar com as entradas mais recentes e imprimir continuamente o registro à medida que novas entradas forem adicionadas. Útil para verificar acionadores que ocorrem em intervalos curtos. Sair com CtrlC.

9.4 Temporizador do systemd: recuperando execuções perdidas

Se um temporizador do systemd estava inativo ou se o sistema estava desativado durante o tempo de execução esperado, os eventos perdidos podem ser acionados imediatamente quando o temporizador é ativado novamente. Para habilitar esse comportamento, adicione a opção de configuração Persistent=true à seção [Timer]:

[Timer]
OnCalendar=Mon..Fri 10:00
Persistent=true
Unit=helloworld.service

9.5 Como migrar do cron para os temporizadores do systemd?

Todas as tarefas cron podem ser migradas para temporizadores do systemd. Estas são as instruções gerais sobre como migrar uma tarefa cron:

  1. Crie um arquivo de serviço executando o script. Consulte o Exemplo 1, “O arquivo de serviço” para obter os detalhes.

  2. Crie um arquivo de temporizador executando o arquivo de serviço. Consulte o Exemplo 2, “O arquivo de temporizador” para obter instruções gerais.

    1. Converta entradas de calendário. O horário é especificado de forma diferente no cron e no systemd. Use os padrões abaixo como modelo de conversão:

      Cron:               Minute Hour Day Month DayOfWeek
      systemd: OnCalendar=DayOfWeek Year-Month-Day Hour:Minute:Second

      Para testar a entrada de calendário convertida, siga as instruções na Seção 5, “Testando entradas de calendário”.

    2. Converta apelidos do cron (@NICK):

      Cron     : systemd timer
      -------- : ----------------------------
      @reboot  : OnBootSec=1s
      @yearly  : OnCalendar=*-01-01 00:00:00
      @annually: OnCalendar=*-01-01 00:00:00
      @monthly : OnCalendar=*-*-01 00:00:00
      @weekly  : OnCalendar=Sun *-*-* 00:00:00
      @daily   : OnCalendar=*-*-* 00:00:00
      @hourly  : OnCalendar=*-*-* *:00:00
    3. Converta atribuições de variáveis. A atribuição de variável do systemd deve ir para a seção [Service]. Você não pode converter MAILTO dessa forma. Consulte a próxima etapa para isso.

      cron: VARIABLE=VALUE
      systemd: Environment="VARIABLE=VALUE"
    4. Configure notificações por e-mail para substituir o recurso MAILTO do cron seguindo as instruções na Seção 6, “Recebendo notificações por e-mail quando há falha no temporizador”.

Exemplo 8: Migração do temporizador do cron para o systemd

Estas são as entradas do crontab que chamam o script helloworld.sh 5 minutos após a inicialização e às 10 horas de segunda-feira a sexta-feira:

@reboot sleep 300 && /usr/local/bin/helloworld.sh
0 10 * * * 1-5 /usr/local/bin/helloworld.sh

O arquivo de serviço do systemd (helloworld.service) que chama o script tem a seguinte aparência:

[Unit]
Description="Hello World script"
[Service]
ExecStart=/usr/local/bin/helloworld.sh

O arquivo de temporizador (helloworld.timer) tem a seguinte aparência:

[Unit]
Description="Run helloworld.service 5min after boot and at 10am every Mon-Fri"
[Timer]
OnBootSec=5min
OnCalendar=Mon..Fri *-*-* 10:00:*
Unit=helloworld.service
[Install]
WantedBy=multi-user.target

10 Para obter mais informações