Como Escrever Arquivos de Unidade systemd - Registrando Servicos Personalizados
O que e um arquivo de unidade systemd?
Um arquivo de unidade systemd e um arquivo de configuracao que registra servicos, pontos de montagem, timers e outros recursos no sistema. Colocando um arquivo .service em /etc/systemd/system/, voce pode gerenciar qualquer script ou aplicacao como um daemon com controle completo do ciclo de vida.
Resumo Rapido
- Localizacao do arquivo de unidade:
/etc/systemd/system/myapp.service - Tres secoes:
[Unit]/[Service]/[Install] - Sempre execute
systemctl daemon-reloadapos criar ou modificar um arquivo de unidade
Estrutura do arquivo de unidade
Um arquivo de unidade tem tres secoes:
[Unit]
Description=My Custom Service
After=network.target
[Service]
ExecStart=/usr/local/bin/myapp
Restart=on-failure
User=myuser
[Install]
WantedBy=multi-user.target
| Secao | Funcao |
|---|---|
[Unit] |
Descricao, ordem de inicializacao, dependencias |
[Service] |
Comando de inicio, politica de restart, usuario |
[Install] |
Alvo para systemctl enable |
1. Registrar um servico personalizado com um arquivo de unidade minimo
A maneira mais rapida de transformar um shell script em um servico 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 configuracao antiga ativa. Execute sempre que modificar um arquivo de unidade.
2. Secao [Unit] - Definindo ordem de inicializacao e dependencias
[Unit] controla metadados do servico e ordenacao de inicializacao.
| Diretiva | Significado |
|---|---|
Description= |
Descricao legivel (exibida em systemctl status) |
After= |
Iniciar este servico apos as unidades especificadas (apenas ordenacao) |
Requires= |
Se a unidade especificada falhar, parar este servico tambem |
Wants= |
Tentar iniciar a unidade especificada, mas continuar se falhar |
ConditionPathExists= |
Iniciar apenas se o arquivo/diretorio especificado existir |
[Unit]
Description=Web Application Backend
After=network.target postgresql.service
Wants=postgresql.service
After=network.target e o padrao para servicos que precisam de acesso a rede. Adicione After=postgresql.service para servicos dependentes de banco de dados. Note que After= controla ordenacao, nao aplicacao de dependencia - use Requires= para dependencias rigidas.
3. Secao [Service] - Comando de inicializacao e comportamento
A secao com mais configuracoes. Estas sao as diretivas principais.
Escolhendo Type=
Type= define como o systemd rastreia o estado do processo.
| Tipo | Caso de uso |
|---|---|
simple (padrao) |
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 e 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 inicio (caminho absoluto obrigatorio) |
ExecStop= |
Comando de parada (padrao SIGTERM se omitido) |
ExecReload= |
Comando de recarga |
Restart= |
Politica de restart: no / on-failure / always |
RestartSec= |
Segundos de espera antes de reiniciar |
User= / Group= |
Usuario e grupo para execucao |
WorkingDirectory= |
Diretorio de trabalho |
EnvironmentFile= |
Caminho para arquivo com variaveis de ambiente |
ExecStart= requer um caminho absoluto - seja o binario diretamente ou um shell com caminho absoluto: /bin/bash /path/to/script.sh. Caminhos relativos como ./script.sh nao funcionam.
Passando variaveis 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= contem senhas, defina as permissoes do arquivo como 600 para que apenas o usuario do servico possa le-lo.
sudo chmod 600 /etc/myapp/env sudo chown root:root /etc/myapp/env
4. Secao [Install] - Controlando o comportamento do enable
Esta secao e lida quando voce executa systemctl enable.
[Install]
WantedBy=multi-user.target
WantedBy=multi-user.target e a escolha padrao. Executar systemctl enable myapp cria um symlink em /etc/systemd/system/multi-user.target.wants/myapp.service, que aciona a inicializacao automatica no boot.
| Valor | Caso de uso |
|---|---|
multi-user.target |
Modo multiusuario padrao (tipico para servidores) |
graphical.target |
Servicos que requerem ambiente grafico |
network-online.target |
Iniciar apenas apos a rede estar totalmente online |
5. Comandos de gerenciamento de servicos
Operacoes comuns apos 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 nao encontrado
myapp.service: control process exited with error code ExecStart=/usr/local/bin/myapp (code=exited, status=203/EXEC)
Correcao: verifique o caminho completo.
which myapp ls -la /usr/local/bin/myapp
Esqueceu daemon-reload
Alteracoes no arquivo de unidade nao sao refletidas, ou "Unit not found" aparece.
sudo systemctl daemon-reload sudo systemctl restart myapp
Permissao negada
journalctl -u myapp -n 20 # myapp.sh: Permission denied
Correcao: verifique a permissao de execucao.
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 tambem se o usuario especificado pode ler o arquivo.
EnvironmentFile nao encontrado
Se EnvironmentFile= aponta para um arquivo ausente, o servico falhara ao iniciar. Para permitir a inicializacao mesmo quando o arquivo esta 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