SystemD - Criando e Gerenciando Serviços no Linux

Tabela de Conteúdo

O systemd é o sistema de inicialização e gerenciamento de serviços padrão na maioria das distribuições Linux modernas. Ele substituiu o antigo SysVinit e oferece recursos avançados como paralelização de inicialização, gerenciamento de dependências, controle de recursos e logging integrado.

Neste post, vamos aprender a criar e gerenciar serviços usando systemd, desde a criação de unit files até o troubleshooting de problemas.

Anatomia de um Unit File

Os unit files do systemd são arquivos de configuração em formato INI que definem como um serviço, timer, mount ou outro recurso do sistema deve ser gerenciado. As seções principais são:

  • [Unit]: Metadados e dependências do serviço
  • [Service]: Configurações específicas do serviço
  • [Install]: Informações de instalação e ativação

Seção [Unit]

Define descrição, dependências e relacionamentos com outros serviços:

[Unit]
Description=Minha Aplicação Web
After=network.target
Wants=network.target

Diretivas comuns:

  • Description: Descrição do serviço
  • After: Inicia após esses serviços
  • Before: Inicia antes desses serviços
  • Requires: Dependência obrigatória (se falhar, este serviço também falha)
  • Wants: Dependência opcional (se falhar, este serviço continua)

Seção [Service]

Define como o serviço será executado:

[Service]
Type=simple
ExecStart=/usr/bin/minha-aplicacao
Restart=always
RestartSec=10
User=www-data
WorkingDirectory=/var/www/app

Diretivas importantes:

  • Type: Tipo de serviço (simple, forking, oneshot, notify)
  • ExecStart: Comando para iniciar o serviço
  • ExecStop: Comando para parar o serviço (opcional)
  • Restart: Quando reiniciar (always, on-failure, never)
  • RestartSec: Tempo de espera antes de reiniciar
  • User: Usuário que executa o serviço
  • WorkingDirectory: Diretório de trabalho

Seção [Install]

Define como o serviço será habilitado:

[Install]
WantedBy=multi-user.target

Criando Seu Primeiro Serviço

Vamos criar um exemplo prático: transformar uma aplicação Python em um serviço systemd.

Exemplo: Aplicação Python

Suponha que você tenha uma aplicação Flask rodando em /opt/myapp/app.py. Vamos criar um serviço para ela:

$ sudo nano /etc/systemd/system/myapp.service

Conteúdo do arquivo:

[Unit]
Description=Minha Aplicação Web Flask
After=network.target

[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapp
Environment="PATH=/opt/myapp/venv/bin"
ExecStart=/opt/myapp/venv/bin/python /opt/myapp/app.py
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Configurações de Restart e Dependências

Controle de Restart

O Restart define quando o systemd deve reiniciar o serviço:

Restart=always        # Sempre reinicia, mesmo após parada normal
Restart=on-failure    # Reinicia apenas em caso de falha
Restart=on-success    # Reinicia apenas após sucesso
Restart=never         # Nunca reinicia automaticamente

O RestartSec define o tempo de espera antes de reiniciar:

RestartSec=10         # Espera 10 segundos
RestartSec=5s         # Espera 5 segundos
RestartSec=1min       # Espera 1 minuto

Dependências entre Serviços

Requires vs Wants:

# Requires: Se o serviço dependente falhar, este também falha
Requires=postgresql.service

# Wants: Se o serviço dependente falhar, este continua
Wants=redis.service

After e Before:

# Inicia após a rede estar disponível
After=network.target

# Inicia antes de outro serviço
Before=nginx.service

Gerenciando o Serviço

Após criar o unit file, recarregue o systemd e gerencie o serviço:

Recarregar Configurações

Sempre que criar ou modificar um unit file, recarregue o systemd:

$ sudo systemctl daemon-reload

Comandos Básicos

$ sudo systemctl start myapp.service

$ sudo systemctl stop myapp.service

$ sudo systemctl restart myapp.service

$ sudo systemctl reload myapp.service

$ sudo systemctl status myapp.service

Habilitar no Boot

Para que o serviço inicie automaticamente ao boot:

$ sudo systemctl enable myapp.service

$ sudo systemctl enable --now myapp.service

Verificar Status

O comando status mostra informações detalhadas:

$ sudo systemctl status myapp.service

Saída exemplo:

● myapp.service - Minha Aplicação Web Flask
   Loaded: loaded (/etc/systemd/system/myapp.service; enabled)
   Active: active (running) since Mon 2022-08-07 10:30:00 UTC; 5min ago
 Main PID: 1234 (python)
    Tasks: 1
   Memory: 50.0M
   CGroup: /system.slice/myapp.service
           └─1234 /opt/myapp/venv/bin/python /opt/myapp/app.py

Troubleshooting com journalctl

O systemd integra logging através do journalctl. Use-o para investigar problemas:

Logs de um Serviço Específico

$ sudo journalctl -u myapp.service

$ sudo journalctl -u myapp.service -f

$ sudo journalctl -u myapp.service -n 50

Filtrar por Tempo

$ sudo journalctl -u myapp.service --since today

$ sudo journalctl -u myapp.service --since "1 hour ago"

$ sudo journalctl -u myapp.service --since "2022-08-07 10:00:00" --until "2022-08-07 11:00:00"

Validação e Debug

Antes de ativar um serviço, valide o unit file:

Verificar Sintaxe

$ sudo systemd-analyze verify /etc/systemd/system/myapp.service

Ver Configuração Completa

Para ver a configuração final (incluindo padrões do systemd):

$ sudo systemctl cat myapp.service

Ver Dependências

# Ver o que este serviço requer
$ systemctl list-dependencies myapp.service

# Ver o que requer este serviço
$ systemctl list-dependencies --reverse myapp.service

Dicas Adicionais

Variáveis de Ambiente

Você pode definir variáveis de ambiente de várias formas:

# Diretamente no unit file
Environment="VAR=valor"

# De um arquivo
EnvironmentFile=/etc/myapp/env.conf

# Múltiplas variáveis
Environment="VAR1=valor1" "VAR2=valor2"

Timers (Agendamento)

O systemd também pode agendar tarefas usando timers:

# /etc/systemd/system/backup.timer
[Unit]
Description=Backup Diário

[Timer]
OnCalendar=daily
OnBootSec=15min

[Install]
WantedBy=timers.target

Simples assim!