>_ josetilabs.com
← blog

03 nov 2026 · linux, systemd, servico · 5 min

Como transformar seu script em um serviço systemd

Um serviço systemd é um arquivo .service com três seções: [Unit], [Service] e [Install]. O systemd lê o arquivo, executa o comando de ExecStart sob o usuário e o diretório configurados, e reinicia o processo quando ele morre, se Restart estiver definido. Os três campos que mudam o comportamento são User, WorkingDirectory e Restart; o limite de memória entra em MemoryMax.

O que cada seção faz

[Unit] descreve o serviço e suas dependências. Description é o texto que aparece em systemctl status. After=network.target garante que a rede suba antes, mas não cria dependência forte; use Wants= ou Requires= se o serviço precisar de outro. [Service] é onde mora o processo: Type, User, WorkingDirectory, EnvironmentFile, ExecStart, Restart, RestartSec, MemoryMax, StandardOutput, StandardError. [Install] diz ao systemctl enable em qual target o serviço entra; multi-user.target é o padrão para servidor.

O artefato: unit completo

ini
[Unit]
Description=Meu serviço de exemplo
After=network.target

[Service]
Type=simple
User=meuusuario
Group=meuusuario
WorkingDirectory=/opt/meu-servico
EnvironmentFile=/opt/meu-servico/meu-servico.env
ExecStart=/opt/meu-servico/meu-servico.sh
Restart=on-failure
RestartSec=5
MemoryMax=256M
StandardOutput=journal
StandardError=journal
SyslogIdentifier=meu-servico

[Install]
WantedBy=multi-user.target

Type=simple significa que o processo principal é o que ExecStart inicia, e o systemd considera o serviço ativo assim que o processo começa. Use oneshot para scripts que rodam e terminam (backup, tarefa pontual), forking para daemons que se descolam do pai, e notify quando o programa avisa o systemd que terminou a inicialização via sd_notify.

User e Group definem quem executa. Se omitir, o serviço roda como root, o que é o erro mais comum em tutoriais. WorkingDirectory é o diretório de trabalho; sem ele, caminhos relativos no script quebram. EnvironmentFile aponta para um arquivo KEY=VALUE; o systemd lê as variáveis e injeta no processo. O arquivo deve ter permissão 600.

text
# /opt/meu-servico/meu-servico.env
# chmod 600, dono meuusuario
API_TOKEN=troque-por-um-valor-real
LOG_LEVEL=info

Restart=on-failure reinicia quando o processo termina com código diferente de zero ou é morto por sinal. RestartSec=5 espera cinco segundos entre tentativas. MemoryMax=256M mata o serviço por OOM do cgroup quando passar do limite; use MemoryHigh para avisar antes. StandardOutput=journal manda stdout para o journal, o que facilita journalctl -u.

Instalar e subir

text
sudo install -o root -g root -m 0644 meu-servico.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now meu-servico.service

daemon-reload relê os arquivos de unit; sem ele o systemd não vê a mudança. enable –now habilita para o próximo boot e inicia agora.

Como verificar

text
systemctl status meu-servico.service
journalctl -u meu-servico.service -f
systemd-analyze verify /etc/systemd/system/meu-servico.service

A saída esperada de status: Active: active (running), Main PID com o PID do bash ou do binário, e Memory abaixo de 256M. systemd-analyze verify não imprime nada quando está tudo certo; qualquer linha de erro aponta o campo e o motivo. Teste o restart derrubando o processo: sudo kill -9 e veja o journal mostrar Scheduled restart job, restart counter is at 1 e um novo PID.

Terminal em dois paineis: systemd-analyze verify sem erro para demo.service, e systemctl status apos kill -9 mostrando novo PID 2835069 e restart counter em 1
A diferença está em verificar antes de subir e em ver o contador de restart subir depois do kill.

Se der errado

216/GROUP (GROUP). Causa: o usuário ou o grupo de User= não existe, ou o serviço user não tem permissão. Correção: crie o usuário com useradd, ou remova User= e Group= para rodar como root e ajuste depois.

203/EXEC. Causa: ExecStart aponta para arquivo inexistente ou sem permissão de execução. Correção: confira o caminho absoluto e rode chmod +x no script.

status=127 (command not found). Causa: o systemd não usa o PATH do seu shell; o comando não tem caminho absoluto. Correção: use caminho absoluto em ExecStart e em qualquer chamada dentro do script.

Serviço não reinicia. Causa: Restart=on-failure não cobre término limpo com código 0, e Restart=on-success não cobre falha. Correção: use Restart=always se quiser reinício em qualquer caso, ou on-abnormal para sinal e timeout.

MemoryMax ignorado. Causa: o kernel ou o cgroup v2 não está ativo, ou a unidade roda fora de um cgroup. Correção: confira systemctl show meu-servico -p MemoryMax e leia memory.current do cgroup; em container use –memory.

Qual type escolher

Type Quando usar Observação
simple processo fica em foreground padrão; systemd considera ativo ao iniciar
oneshot script roda e termina combine com RemainAfterExit=yes se precisar de status ativo
forking daemon se descola do pai systemd espera o pai sair; desencorajado
notify programa avisa via sd_notify melhor para serviços com inicialização lenta
idle espera outros jobs terminarem raramente necessário

FAQ

O serviço carrega .bashrc? Não. O systemd não lê arquivo de perfil. Declare variáveis em EnvironmentFile ou em Environment=.

Posso rodar como root? Pode, mas não deve. Crie um usuário dedicado com useradd –system –no-create-home e use User= e Group=. Root só quando o serviço precisa de porta abaixo de 1024 ou de capacidade específica; nesse caso prefira AmbientCapabilities=CAP_NET_BIND_SERVICE.

Como ver os logs? journalctl -u meu-servico -e abre no fim; -f segue em tempo real; –since “1 hour ago” filtra por tempo.

Como desativar sem apagar? systemctl disable –now meu-servico.service para o boot e agora; para pausar temporariamente, systemctl stop.

Como passar argumentos ao script? ExecStart=/opt/meu-servico/meu-servico.sh –port 8080. Se precisar de shell, use ExecStart=/bin/bash -c ‘…’ com cuidado de quoting.

Fontes

systemd.service(5) e systemd.exec(5), conferidos em novembro de 2026. Limites de memória em systemd.resource-control(5). Para logs, journalctl para achar o erro. Para segredos em arquivo, env e segredos em arquivo. Para limitar contêiner, como limitar memória de contêiner. Para rotina com cron, cron do jeito certo.

Leia também

// Por e-mail

Os textos publicados aqui também vão por e-mail. O envio ainda não começou: quem deixar o endereço agora entra na primeira lista.

Guardo só o seu e-mail, a data e o registro desta autorização. Sem cookies, sem rastreador e nada compartilhado com terceiros. Detalhes na política de privacidade.