Como Escrever Arquivos de Unidade systemd - Registrando Serviços Personalizados
O que é um arquivo de unidade systemd?
Um arquivo de unidade systemd é um arquivo de configuração que registra serviços, pontos de montagem, timers e outros recursos no sistema. Colocando um arquivo .service em /etc/systemd/system/, você pode gerenciar qualquer script ou aplicação como um daemon com controle completo do ciclo de vida.
Resumo Rápido
- Localização do arquivo de unidade:
/etc/systemd/system/myapp.service - Três seções:
[Unit]/[Service]/[Install] - Sempre execute
systemctl daemon-reloadapós criar ou modificar um arquivo de unidade
Estrutura do arquivo de unidade
Um arquivo de unidade tem três seções:
[Unit]
Description=My Custom Service
After=network.target
[Service]
ExecStart=/usr/local/bin/myapp
Restart=on-failure
User=myuser
[Install]
WantedBy=multi-user.target
| Seção | Função |
|---|---|
[Unit] |
Descrição, ordem de inicialização, dependências |
[Service] |
Comando de início, política de restart, usuário |
[Install] |
Alvo para systemctl enable |
1. Registrar um serviço personalizado com um arquivo de unidade mínimo
A maneira mais rápida de transformar um shell script em um serviço gerenciado.
1-1. Criar o script
sudo tee /usr/local/bin/myapp.sh > /dev/null << 'EOF'
#!/bin/bash
while true; do
echo "$(date) running" >> /var/log/myapp.log
sleep 10
done
EOF
sudo chmod +x /usr/local/bin/myapp.sh1-2. Criar o arquivo de unidade
sudo tee /etc/systemd/system/myapp.service > /dev/null << 'EOF' [Unit] Description=My Application After=network.target [Service] ExecStart=/usr/local/bin/myapp.sh Restart=on-failure [Install] WantedBy=multi-user.target EOF
1-3. Recarregar, habilitar e iniciar
sudo systemctl daemon-reload sudo systemctl enable --now myapp sudo systemctl status myapp
● myapp.service - My Application
Loaded: loaded (/etc/systemd/system/myapp.service; enabled)
Active: active (running) since Sun 2026-05-31 12:00:00 UTC; 3s ago
Main PID: 12345 (myapp.sh)
Esquecer daemon-reload causa erros "Unit not found" ou deixa a configuração antiga ativa. Execute sempre que modificar um arquivo de unidade.
2. Seção [Unit] - Definindo ordem de inicialização e dependências
[Unit] controla metadados do serviço e ordenação de inicialização.
| Diretiva | Significado |
|---|---|
Description= |
Descrição legível (exibida em systemctl status) |
After= |
Iniciar este serviço após as unidades especificadas (apenas ordenação) |
Requires= |
Se a unidade especificada falhar, parar este serviço também |
Wants= |
Tentar iniciar a unidade especificada, mas continuar se falhar |
ConditionPathExists= |
Iniciar apenas se o arquivo/diretório especificado existir |
[Unit]
Description=Web Application Backend
After=network.target postgresql.service
Wants=postgresql.service
After=network.target é o padrão para serviços que precisam de acesso à rede. Adicione After=postgresql.service para serviços dependentes de banco de dados. Note que After= controla ordenação, não aplicação de dependência - use Requires= para dependências rigidas.
3. Seção [Service] - Comando de inicialização e comportamento
A seção com mais configurações. Estas são as diretivas principais.
Escolhendo Type=
Type= define como o systemd rastreia o estado do processo.
| Tipo | Caso de uso |
|---|---|
simple (padrão) |
Um processo que permanece em primeiro plano |
forking |
Um processo que se daemoniza (faz fork) |
oneshot |
Um script que executa uma vez e termina |
notify |
Um processo que sinaliza prontidao com READY=1 |
Para a maioria dos casos, simple ou oneshot é a escolha certa.
Diretivas principais
[Service]
Type=simple
ExecStart=/usr/local/bin/myapp --config /etc/myapp/config.yml
ExecStop=/bin/kill -TERM $MAINPID
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5
User=www-data
Group=www-data
WorkingDirectory=/var/lib/myapp
EnvironmentFile=/etc/myapp/env
| Diretiva | Significado |
|---|---|
ExecStart= |
Comando de início (caminho absoluto obrigatório) |
ExecStop= |
Comando de parada (padrão SIGTERM se omitido) |
ExecReload= |
Comando de recarga |
Restart= |
Política de restart: no / on-failure / always |
RestartSec= |
Segundos de espera antes de reiniciar |
User= / Group= |
Usuário e grupo para execução |
WorkingDirectory= |
Diretório de trabalho |
EnvironmentFile= |
Caminho para arquivo com variáveis de ambiente |
ExecStart= requer um caminho absoluto - seja o binário diretamente ou um shell com caminho absoluto: /bin/bash /path/to/script.sh. Caminhos relativos como ./script.sh não funcionam.
Passando variáveis de ambiente
[Service]
Environment="NODE_ENV=production"
Environment="PORT=3000"
EnvironmentFile=/etc/myapp/env
Exemplo /etc/myapp/env:
DB_HOST=localhost
DB_PORT=5432
SECRET_KEY=changeme
Se EnvironmentFile= contém senhas, defina as permissões do arquivo como 600 para que apenas o usuário do serviço possa lê-lo.
sudo chmod 600 /etc/myapp/env sudo chown root:root /etc/myapp/env
4. Seção [Install] - Controlando o comportamento do enable
Esta seção é lida quando você executa systemctl enable.
[Install]
WantedBy=multi-user.target
WantedBy=multi-user.target é a escolha padrão. Executar systemctl enable myapp cria um symlink em /etc/systemd/system/multi-user.target.wants/myapp.service, que aciona a inicialização automática no boot.
| Valor | Caso de uso |
|---|---|
multi-user.target |
Modo multiusuário padrão (típico para servidores) |
graphical.target |
Serviços que requerem ambiente gráfico |
network-online.target |
Iniciar apenas após a rede estar totalmente online |
5. Comandos de gerenciamento de serviços
Operações comuns após criar um arquivo de unidade:
# Recarregar arquivos de unidade (obrigatorio apos qualquer alteracao) sudo systemctl daemon-reload # Habilitar (inicio automatico no boot) + iniciar imediatamente sudo systemctl enable --now myapp # Verificar status sudo systemctl status myapp # Reiniciar sudo systemctl restart myapp # Recarregar configuracao (requer ExecReload) sudo systemctl reload myapp # Parar sudo systemctl stop myapp # Desabilitar inicio automatico sudo systemctl disable myapp # Ver logs recentes (ultimas 50 linhas) journalctl -u myapp -n 50 --no-pager
6. Falhas comuns e como corrigi-las
Caminho do ExecStart não encontrado
myapp.service: control process exited with error code ExecStart=/usr/local/bin/myapp (code=exited, status=203/EXEC)
Correção: verifique o caminho completo.
which myapp ls -la /usr/local/bin/myapp
Esqueceu daemon-reload
Alterações no arquivo de unidade não são refletidas, ou "Unit not found" aparece.
sudo systemctl daemon-reload sudo systemctl restart myapp
Permissão negada
journalctl -u myapp -n 20 # myapp.sh: Permission denied
Correção: verifique a permissão de execução.
ls -la /usr/local/bin/myapp.sh # Se falta permissao de execucao: sudo chmod +x /usr/local/bin/myapp.sh
Se User= estiver definido, verifique também se o usuário especificado pode ler o arquivo.
EnvironmentFile não encontrado
Se EnvironmentFile= aponta para um arquivo ausente, o serviço falhará ao iniciar. Para permitir a inicialização mesmo quando o arquivo está ausente, prefixe o caminho com -:
EnvironmentFile=-/etc/myapp/env
Cheatsheet do fluxo completo
# 1. Criar o script sudo vim /usr/local/bin/myapp.sh sudo chmod +x /usr/local/bin/myapp.sh # 2. Criar o arquivo de unidade sudo vim /etc/systemd/system/myapp.service # 3. Registrar e iniciar sudo systemctl daemon-reload sudo systemctl enable --now myapp # 4. Verificar sudo systemctl status myapp journalctl -u myapp -f