Introdução
O systemd é o gestor de serviços padrão nas distribuições Linux modernas. Compreender o systemd é essencial para implementar e gerir aplicações em produção — desde iniciar serviços no arranque até monitorizar o seu estado e gerir dependências. Este guia aborda a administração prática do systemd para a implementação de aplicações.
Noções Básicas de Gestão de Serviços
Comandos Comuns
# Iniciar/parar/reiniciar serviço
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx
# Recarregar a configuração sem reiniciar
sudo systemctl reload nginx
# Ativar/desativar o serviço no arranque
sudo systemctl enable nginx
sudo systemctl disable nginx
# Ativar e iniciar num único comando
sudo systemctl enable --now nginx
# Verificar o estado do serviço
sudo systemctl status nginx
# Listar todos os serviços
sudo systemctl list-units --type=service
# Listar serviços ativados
sudo systemctl list-unit-files --type=service --state=enabled
Saída do Estado do Serviço
● nginx.service - A high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Mon 2024-01-15 10:30:00 UTC; 5h ago
Docs: man:nginx(8)
Main PID: 1234 (nginx)
Tasks: 5 (limit: 4915)
Memory: 12.5M
CPU: 1.234s
CGroup: /system.slice/nginx.service
├─1234 nginx: master process /usr/sbin/nginx
└─1235 nginx: worker process
Indicadores-chave:
- Active: Estado atual (running, dead, failed)
- Main PID: ID do processo principal
- Memory/CPU: Utilização de recursos
Criar Serviços Personalizados
Unidade de Serviço Básica
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
Documentation=https://myapp.example.com/docs
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/node /var/www/myapp/server.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
# Aplicar alterações
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
Tipos de Serviço
# Simple (predefinição): o processo principal é o serviço
Type=simple
ExecStart=/usr/bin/myapp
# Forking: o processo faz fork e o processo pai termina
Type=forking
PIDFile=/var/run/myapp.pid
ExecStart=/usr/bin/myapp --daemon
# Oneshot: o processo executa uma vez e termina
Type=oneshot
ExecStart=/usr/bin/setup-script.sh
RemainAfterExit=yes
# Notify: o processo sinaliza que está pronto
Type=notify
ExecStart=/usr/bin/myapp --notify
Configuração de Ambiente
[Service]
# Variáveis de ambiente inline
Environment=NODE_ENV=production
Environment=PORT=3000
# Ficheiro de ambiente
EnvironmentFile=/etc/myapp/environment
# Vários ficheiros de ambiente
EnvironmentFile=-/etc/myapp/environment # - significa opcional
EnvironmentFile=/etc/myapp/secrets
# /etc/myapp/environment
NODE_ENV=production
PORT=3000
DATABASE_URL=postgres://localhost/myapp
Limites de Recursos
Memória e CPU
[Service]
# Limites de memória
MemoryMax=512M
MemoryHigh=400M
# Limites de CPU
CPUQuota=50%
CPUWeight=100
# Descritores de ficheiro
LimitNOFILE=65535
# Limites de processos
LimitNPROC=4096
# Core dumps
LimitCORE=infinity
Limites de I/O
[Service]
IOWeight=500
IOReadBandwidthMax=/dev/sda 10M
IOWriteBandwidthMax=/dev/sda 5M
Reforço de Segurança
Opções de Isolamento
[Service]
# Executar como não-root
User=myapp
Group=myapp
# Restrições do sistema de ficheiros
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/myapp /var/log/myapp
ReadOnlyPaths=/etc/myapp
# Diretório temporário
PrivateTmp=yes
# Isolamento de rede
PrivateNetwork=yes # Sem acesso à rede
# Acesso a dispositivos
PrivateDevices=yes
# Impedir escalada de privilégios
NoNewPrivileges=yes
# Filtragem de chamadas de sistema
SystemCallFilter=@system-service
SystemCallErrorNumber=EPERM
Restrições de Capacidades
[Service]
# Remover todas as capacidades, exceto as necessárias
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
# Remover todas as capacidades
CapabilityBoundingSet=
Supervisão de Processos
Políticas de Reinício
[Service]
# Opções de reinício: no, on-success, on-failure, on-abnormal, on-watchdog, on-abort, always
Restart=on-failure
# Tempo entre reinícios
RestartSec=5s
# Número máximo de tentativas de reinício
StartLimitIntervalSec=300
StartLimitBurst=5
# Ações quando o limite é atingido
# FailureAction=reboot
# SuccessAction=poweroff
Watchdog
[Service]
Type=notify
WatchdogSec=30s
# A aplicação deve chamar sd_notify(0, "WATCHDOG=1") periodicamente
Comandos Pré/Pós
[Service]
ExecStartPre=/usr/bin/check-config.sh
ExecStart=/usr/bin/myapp
ExecStartPost=/usr/bin/notify-started.sh
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/usr/bin/graceful-stop.sh
ExecStopPost=/usr/bin/cleanup.sh
Registo com Journal
Visualizar Logs
# Logs do serviço
sudo journalctl -u myapp
# Seguir logs
sudo journalctl -u myapp -f
# Últimas 100 linhas
sudo journalctl -u myapp -n 100
# Desde o arranque
sudo journalctl -u myapp -b
# Intervalo de tempo
sudo journalctl -u myapp --since "2024-01-15 10:00:00" --until "2024-01-15 12:00:00"
# Filtro de prioridade (err e superior)
sudo journalctl -u myapp -p err
# Saída em JSON
sudo journalctl -u myapp -o json
# Utilização de disco
sudo journalctl --disk-usage
Configuração de Logs
[Service]
# Enviar a saída para o journal
StandardOutput=journal
StandardError=journal
# Ou para ficheiro
StandardOutput=append:/var/log/myapp/output.log
StandardError=append:/var/log/myapp/error.log
# Identificador de syslog
SyslogIdentifier=myapp
Persistência do Journal
# Tornar os logs persistentes
sudo mkdir -p /var/log/journal
sudo systemd-tmpfiles --create --prefix /var/log/journal
# Configurar retenção
sudo vi /etc/systemd/journald.conf
# SystemMaxUse=500M
# MaxRetentionSec=1month
sudo systemctl restart systemd-journald
Timers (Substituição do Cron)
Unidade Timer
# /etc/systemd/system/backup.timer
[Unit]
Description=Daily backup timer
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
# /etc/systemd/system/backup.service
[Unit]
Description=Backup service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Agendamentos de Timer
# Expressões de calendário
OnCalendar=hourly
OnCalendar=daily
OnCalendar=weekly
OnCalendar=monthly
OnCalendar=*-*-* 00:00:00 # Diariamente à meia-noite
OnCalendar=Mon *-*-* 00:00:00 # Todas as segundas-feiras
OnCalendar=*-*-* *:00:00 # A cada hora
OnCalendar=*-*-* *:*:00 # A cada minuto
# Temporização relativa
OnBootSec=5min # 5 minutos após o arranque
OnUnitActiveSec=1h # 1 hora após a última ativação
Gerir Timers
# Listar timers
sudo systemctl list-timers
# Ativar timer
sudo systemctl enable --now backup.timer
# Executar imediatamente o serviço associado
sudo systemctl start backup.service
Ativação por Socket
# /etc/systemd/system/myapp.socket
[Unit]
Description=My App Socket
[Socket]
ListenStream=8080
Accept=no
[Install]
WantedBy=sockets.target
# /etc/systemd/system/myapp.service
[Unit]
Description=My App
Requires=myapp.socket
[Service]
ExecStart=/usr/bin/myapp
StandardInput=socket
O serviço só é iniciado quando é recebida uma ligação no socket.
Serviços Multi-instância
# /etc/systemd/system/[email protected]
[Unit]
Description=My App instance %i
[Service]
ExecStart=/usr/bin/myapp --instance %i --port %i
User=www-data
[Install]
WantedBy=multi-user.target
# Iniciar várias instâncias
sudo systemctl enable --now myapp@3000
sudo systemctl enable --now myapp@3001
sudo systemctl enable --now myapp@3002
# Gerir todas as instâncias
sudo systemctl restart 'myapp@*'
Depuração
# Verificar a sintaxe do ficheiro de unidade
sudo systemd-analyze verify /etc/systemd/system/myapp.service
# Mostrar a configuração da unidade
sudo systemctl show myapp
# Mostrar as dependências da unidade
sudo systemctl list-dependencies myapp
# Verificar o desempenho do arranque
systemd-analyze
systemd-analyze blame
systemd-analyze critical-chain myapp.service
Boas Práticas
- Utilize
Type=notify sempre que possível para um estado preciso - Defina políticas de reinício adequadas para resiliência
- Aplique opções de reforço de segurança
- Utilize ficheiros de ambiente para configuração
- Configure limites de recursos para evitar processos descontrolados
- Utilize timers em vez de cron para tarefas agendadas
- Monitorize com journalctl e defina a retenção de logs
Conclusão
O systemd disponibiliza capacidades poderosas de gestão de serviços. Crie ficheiros de unidade adequados com reforço de segurança, configure políticas de reinício apropriadas e utilize timers para tarefas agendadas. Os padrões neste guia ajudam a implementar e gerir serviços de produção fiáveis.