Pular para o conteúdo principal

Capítulo 8.2 - Serviços Personalizados

Objetivos de Aprendizagem​

Ao final deste capítulo, você será capaz de:

  • Criar um arquivo unit do systemd
  • Configurar um serviço personalizado
  • Compreender as seções de um unit file
  • Gerenciar dependências
  • Criar serviços para scripts

Estrutura de um Unit File​

Localização​

# Sistema
/etc/systemd/system/

# Usuário
~/.config/systemd/user/

Prioridade:

  • /etc/systemd/system/ (sistema) > /usr/lib/systemd/system/ (pacotes)

Formato Básico​

[Unit]
Description=Descrição do serviço
After=network.target

[Service]
Type=simple
ExecStart=/caminho/para/comando
Restart=always

[Install]
WantedBy=multi-user.target

Seções Principais​

[Unit]​

[Unit]
Description=Meu Serviço Personalizado
Documentation=man:meu-servico(1)
After=network.target sshd.service
Before=some-service.service
Requires=network.target
Wants=sshd.service
Conflicts=old-service.service

Diretivas:

  • Description: Descrição do serviço
  • After: Inicia após estas unidades
  • Before: Inicia antes destas unidades
  • Requires: Dependência forte (falha se a dependência falhar)
  • Wants: Dependência fraca (continua se a dependência falhar)
  • Conflicts: Não pode rodar ao mesmo tempo

[Service]​

[Service]
Type=simple
ExecStart=/usr/local/bin/meu-script.sh
ExecStartPre=/bin/echo "Iniciando"
ExecStartPost=/bin/echo "Iniciado"
ExecStop=/bin/echo "Parando"
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=10
User=meuusuario
Group=meugrupo
WorkingDirectory=/var/lib/meuservico
Environment="VAR1=valor1"
EnvironmentFile=/etc/meuservico/env
StandardOutput=journal
StandardError=journal

Tipos:

  • simple: Comando principal (padrão)
  • forking: Fork em background
  • oneshot: Execução única
  • notify: Notifica o systemd quando estiver pronto

Restart:

  • no: Não reinicia
  • always: Sempre reiniciar
  • on-failure: Reiniciar em caso de falha
  • on-success: Reiniciar em caso de sucesso

[Install]​

[Install]
WantedBy=multi-user.target
Alias=meuservico.service

Targets comuns:

  • multi-user.target: Modo multiusuário
  • graphical.target: Modo gráfico
  • default.target: Target padrão

Exemplos Práticos​

Serviço Simples​

# /etc/systemd/system/meu-servico.service
[Unit]
Description=Meu Serviço Simples
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/meu-script.sh
Restart=always
RestartSec=10
User=www-data
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Ativar:

sudo systemctl daemon-reload
sudo systemctl enable meu-servico
sudo systemctl start meu-servico

Serviço com Script​

#!/bin/bash
# /usr/local/bin/meu-script.sh
# Script de serviço

# Função de limpeza
cleanup() {
echo "Parando o serviço"
# Limpeza...
exit 0
}

# Trap signals
trap cleanup SIGTERM SIGINT

# Loop principal
while true; do
# Trabalho...
echo "Serviço ativo: $(date)"
sleep 60
done

Unit file:

[Unit]
Description=Serviço com Script
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/meu-script.sh
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Serviço Forking​

[Unit]
Description=Serviço Forking
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/bin/daemon --daemonize
PIDFile=/var/run/daemon.pid
Restart=always

[Install]
WantedBy=multi-user.target

Serviço Oneshot​

[Unit]
Description=Script Oneshot
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/init-script.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Variáveis de Ambiente​

No Unit File​

[Service]
Environment="VAR1=valor1"
Environment="VAR2=valor2"
EnvironmentFile=/etc/meuservico/env

Arquivo de Ambiente​

# /etc/meuservico/env
VAR1=valor1
VAR2=valor2
VAR3="valor com espaços"

Gerenciamento de Logs​

Journal do systemd​

# Ver logs do serviço
sudo journalctl -u meu-servico

# Seguir logs
sudo journalctl -u meu-servico -f

# Logs recentes
sudo journalctl -u meu-servico -n 50

# Desde data
sudo journalctl -u meu-servico --since "2024-01-01"

Redirecionamento​

[Service]
# Para o journal (padrão)
StandardOutput=journal
StandardError=journal

# Para arquivo
StandardOutput=file:/var/log/meuservico.log
StandardError=file:/var/log/meuservico-error.log

# Ignorar
StandardOutput=null
StandardError=null

Boas Práticas​

Estrutura​

[Unit]
# Descrição clara
# Dependências apropriadas

[Service]
# Tipo correto
# User/Group não-root se possível
# Restart apropriado
# Logging configurado

[Install]
# Target apropriado

Segurança​

[Service]
# Não usar root se possível
User=serviceuser
Group=servicegroup

# Limitar capacidades
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
NoNewPrivileges=true

# Chroot se possível
RootDirectory=/var/lib/meuservico

Resumo​

Neste capítulo, você aprendeu:

Unit files: Estrutura [Unit], [Service], [Install]
Tipos: simple, forking, oneshot, notify
Dependências: After, Before, Requires, Wants
Restart: always, on-failure, never
Ambiente: Environment, EnvironmentFile
Logs: journalctl, redirecionamento para arquivos
Prática: Criar serviços para scripts e aplicações


Próximos Passos​

Capítulo 8.3: Cron Avançado e systemd Timers
Módulo 9: Segurança de Sistema


Capítulo criado em: Dezembro 2024