systemd: como criar e gerenciar serviços
systemd: aprenda a criar e gerenciar serviços com aplicações práticas e recomendações para quem está começando ou quer revisar o básico.
Você sobe a aplicação na VPS com nohup node server.js &, fecha o SSH e vai dormir tranquilo. De manhã o serviço está fora do ar: o processo morreu durante a noite e ninguém o reergueu, ou a sessão SSH caiu e levou tudo junto. Pior cenário: a máquina reiniciou por causa de um update de kernel e sua aplicação simplesmente não voltou. nohup e screen foram feitos para manter um comando vivo enquanto você não está olhando, não para gerenciar um serviço de produção. Para isso existe o systemd, e ele já está instalado na sua distro.
Este artigo mostra como transformar uma aplicação num serviço gerenciado de verdade: que reinicia sozinho, sobe no boot e tem log centralizado. Se em algum momento a máquina ficar sem espaço por causa de log mal configurado, vale ler depois como investigar falta de espaço em disco no Linux — journald cheio é uma causa comum.
Por que systemd em vez de nohup ou screen
nohup e screen/tmux não monitoram o processo. Se ele crashar, fica morto. Não sobem no boot. Não têm log estruturado. Não controlam dependências de ordem de inicialização. O systemd faz tudo isso: reinicia em caso de falha, integra com o boot, centraliza logs no journald, e expressa que seu serviço depende da rede ou do banco estar de pé.
A troca é uma única vez: você escreve um arquivo de unit e nunca mais pensa em manter o processo vivo na mão.
Anatomia de um arquivo .service
Um unit fica em /etc/systemd/system/<nome>.service e tem três seções:
[Unit]— metadados e dependências: descrição, o que precisa estar de pé antes.[Service]— como rodar: o comando, o usuário, política de restart, variáveis de ambiente.[Install]— quando habilitado no boot, em qual "target" ele se enquadra.
Aqui um exemplo real para uma aplicação Node:
[Unit]
Description=API Quick Tools
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=deploy
Group=deploy
WorkingDirectory=/opt/quicktools
EnvironmentFile=/opt/quicktools/.env
ExecStart=/usr/bin/node /opt/quicktools/server.js
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
Cada linha aqui resolve um problema que nohup deixava em aberto: roda como usuário não-root, lê env de arquivo, reinicia em falha com 5 segundos de espera, e sobe no boot.
Restart=: a política que separa serviço de script
A diretiva Restart= define quando o systemd reergue o processo:
no— nunca reinicia (default). É efetivamente umnohup.on-failure— reinicia só se o processo sair com código != 0 ou for morto por sinal. É o que você quer na maioria dos casos.always— reinicia até em saída limpa (código 0). Útil para serviços que nunca deveriam terminar, mas mascara bugs de saída intencional.
Combine com RestartSec= para não entrar em loop de restart instantâneo quando o serviço crasha na inicialização. E se quiser um teto, StartLimitIntervalSec + StartLimitBurst no [Unit] impedem que o systemd fique reiniciando um serviço quebrado infinitamente.
journalctl: onde foram parar os logs
Como o exemplo manda stdout/stderr para journal, todo log vai para o journald. Os comandos do dia a dia:
# logs do serviço, do mais recente
journalctl -u quicktools.service -n 100 --no-pager
# acompanhar em tempo real (tipo tail -f)
journalctl -u quicktools.service -f
# só de hoje, com prioridade de erro
journalctl -u quicktools.service --since today -p err
Não há mais arquivo de log perdido em /var/log ou redirecionado para nohup.out. Tudo fica indexado por unit, por tempo e por prioridade. O preço é gerenciar o tamanho do journal — daí a relação com falta de espaço em disco.
enable vs start: a confusão clássica
Os dois comandos parecem iguais e fazem coisas diferentes:
systemctl start quicktools— inicia agora, nesta sessão. Não sobrevive a reboot.systemctl enable quicktools— registra para subir no próximo boot. Não inicia agora.
Você quase sempre quer os dois. O atalho é systemctl enable --now quicktools: habilita no boot e inicia imediatamente. Esquecer o enable é o motivo número um de "funcionou, reiniciei a máquina e sumiu".
Lendo status e diagnosticando
systemctl status quicktools é o primeiro comando quando algo dá errado:
systemctl status quicktools.service
Ele mostra se está active (running), failed, ou inactive, o PID, há quanto tempo está de pé, e as últimas linhas de log. Se aparecer failed, vá direto para o journalctl -u para ver o stack trace.
Pegadinhas comuns
Três coisas que travam quase todo mundo na primeira vez:
daemon-reload: depois de editar o.service, rodesystemctl daemon-reloadantes de reiniciar o serviço. Sem isso o systemd continua usando a versão antiga em cache e você jura que sua mudança não fez nada.WorkingDirectory: se a aplicação lê arquivos por caminho relativo, definaWorkingDirectoryexplicitamente. O systemd inicia no/por padrão, não no diretório do binário, e caminhos relativos quebram.- Variáveis de ambiente: o systemd não carrega seu
~/.bashrcnem o.envautomaticamente. UseEnvironment=para variáveis pontuais ouEnvironmentFile=apontando para um arquivo. PATH também é mínimo — por isso oExecStartusa caminho absoluto para o binário.
Perguntas frequentes
Qual a diferença entre enable e start no systemd?
start inicia o serviço imediatamente na sessão atual e não sobrevive a reboot. enable registra o serviço para subir automaticamente no próximo boot, mas não o inicia agora. Use systemctl enable --now <serviço> para fazer os dois de uma vez.
Por que minha alteração no arquivo .service não fez efeito?
Você provavelmente esqueceu o systemctl daemon-reload. O systemd mantém os units em cache na memória e só relê os arquivos quando você manda recarregar. Rode daemon-reload e depois restart do serviço sempre que editar o unit.
Devo usar Restart=always ou Restart=on-failure?
on-failure na maioria dos casos: reinicia só quando o processo sai com erro ou é morto por sinal, e respeita uma saída limpa. always reinicia até em saída código 0, o que é útil para serviços que nunca deveriam terminar, mas mascara situações em que o processo terminou de propósito.
O systemd carrega meu .env automaticamente?
Não. Ele não lê ~/.bashrc nem nenhum .env por conta própria. Você precisa declarar EnvironmentFile=/caminho/.env na seção [Service], ou definir variáveis uma a uma com Environment=.
O que fica do systemd no seu fluxo
Trocar nohup por systemd é meia hora de trabalho que se paga na primeira madrugada em que o serviço crasha e reergue sozinho sem te acordar. Escreva o unit com WorkingDirectory e EnvironmentFile corretos, escolha Restart=on-failure com RestartSec, rode enable --now, e use journalctl -u -f quando precisar olhar. Lembre do daemon-reload toda vez que editar o arquivo. A partir daí seu serviço sobe no boot, sobrevive a crashes e tem log centralizado — três coisas que nohup & nunca vai te dar.
- 01 Nubank Croma: o que vem no plano, quanto custa e pra quem realmente compensa O Nubank lançou o Croma, um plano de média renda entre o cartão gratuito e o Ultravioleta. Veja o que está incluído, o cashback real, os R$ 39 de mensalidade (e como zerar) e faça a conta antes de aderir.
- 02 Como documentar projetos no GitHub: o README que importa O README é a porta de entrada e quase a única doc que será lida. Veja a estrutura que funciona, os arquivos de apoio e como documentar o porquê.