Poupe até 53% em Servidores VPS, escolha agora. Oferta limitada.

Manual do Systemd: unidades, targets e dependências no Linux

20 min de leitura  ·  Guia técnico

Systemd é o sistema de inicialização e gerenciamento de serviços padrão na maioria das distribuições Linux modernas, incluindo Debian 12, Rocky Linux 9 e AlmaLinux 9. Ele controla como processos são iniciados, monitorados e encerrados por meio de arquivos de configuração chamados unit files, organizados em targets e conectados por relações de dependência declarativas. Para dominar o systemd, siga estes passos essenciais:

  1. Entenda a estrutura de uma unit file e suas seções obrigatórias
  2. Aprenda a diferença entre os tipos de unidades: service, socket, timer, mount
  3. Crie e ative um serviço personalizado com reinício automático
  4. Configure dependências com Wants=, Requires= e After=
  5. Gerencie targets para controlar o estado do sistema
  6. Use journalctl para diagnosticar falhas com precisão

Pré-requisitos para trabalhar com systemd

  • Acesso root ou usuário com privilégios sudo ao servidor
  • Distribuição Linux com systemd: Debian 12, Rocky Linux 9, AlmaLinux 9, Ubuntu 24.04 LTS ou equivalente
  • Versão do systemd 252 ou superior (verifique com systemctl --version)
  • Editor de texto disponível: nano, vim ou micro
  • Familiaridade básica com terminal Linux — consulte o guia Acessando servidores VPS Linux da AviraHost se precisar de ajuda para conectar via SSH

Anatomia de uma unit file no systemd

Uma unit file é o bloco fundamental do systemd: um arquivo de texto declarativo que descreve como um recurso do sistema deve se comportar. Diferente dos scripts de inicialização do SysV, você não escreve lógica imperativa — você declara intenções, e o systemd resolve a ordem de execução automaticamente.

Os arquivos de unidade residem em dois locais principais:

  • /lib/systemd/system/ — unidades fornecidas pelos pacotes do sistema (não edite diretamente)
  • /etc/systemd/system/ — personalizações do administrador, têm prioridade sobre o diretório anterior

A estrutura básica de uma unit file de serviço contém três seções obrigatórias:

[Unit]
Description=Minha Aplicação Web
Documentation=https://exemplo.com/docs
After=network.target
Wants=network-online.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/minhaapp
ExecStart=/opt/minhaapp/bin/server --port 8080
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

Cada seção tem uma função específica:

  • [Unit] — metadados, descrição e declaração de dependências (ordem e requisitos)
  • [Service] — comportamento do processo: como iniciar, parar, reiniciar e com qual usuário
  • [Install] — define em qual target a unidade será ativada quando habilitada com systemctl enable

O campo Type= merece atenção especial. Os valores mais comuns são:

  • simple — o processo principal é o iniciado pelo ExecStart (padrão)
  • forking — o processo pai faz fork e encerra; o filho continua (daemons tradicionais)
  • oneshot — executa uma vez e encerra; systemd aguarda a conclusão antes de continuar
  • notify — o serviço envia uma notificação via sd_notify() quando está pronto
  • exec — similar ao simple, mas o serviço é considerado iniciado apenas após o exec bem-sucedido

Tipos de unidades além do .service

O systemd gerencia muito mais do que serviços. Cada tipo de unidade tem sua extensão de arquivo e propósito específico, formando um ecossistema completo de gerenciamento de recursos do sistema.

  • .service — processos e daemons (nginx.service, sshd.service)
  • .socket — ativação por socket; o serviço só inicia quando há conexão de entrada
  • .timer — substituto moderno do cron, com suporte a calendários e monotonic timers
  • .mount — pontos de montagem do sistema de arquivos
  • .target — agrupamentos de unidades que representam estados do sistema
  • .path — monitora arquivos ou diretórios e ativa serviços quando há mudanças
  • .slice — agrupa processos para controle de recursos via cgroups

Um exemplo prático de timer que substitui uma entrada no cron:

[Unit]
Description=Backup diário do banco de dados
Requires=backup-db.service

[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true

[Install]
WantedBy=timers.target

Com Persistent=true, se o servidor estiver desligado no horário agendado, o timer executará o serviço assim que o sistema iniciar. Isso é uma vantagem significativa sobre o cron tradicional.

Para listar todos os timers ativos e ver quando cada um executará pela próxima vez:

systemctl list-timers --all
NEXT                        LEFT          LAST                        PASSED       UNIT                         ACTIVATES
Thu 2024-11-14 02:30:00 -03 8h left       Wed 2024-11-13 02:30:01 -03 15h ago      backup-db.timer              backup-db.service
Thu 2024-11-14 06:17:42 -03 12h left      Wed 2024-11-13 06:17:42 -03 11h ago      apt-daily.timer              apt-daily.service

Dependências no systemd: Wants, Requires, After e Before

O sistema de dependências do systemd é declarativo e resolve a ordem de inicialização automaticamente. Compreender as diferenças entre as diretivas é essencial para evitar falhas em cascata e garantir que serviços iniciem na sequência correta.

As principais diretivas de dependência são:

  • Wants= — dependência fraca: se a unidade listada falhar, a unidade principal continua normalmente
  • Requires= — dependência forte: se a unidade listada falhar ou for parada, a unidade principal também é interrompida
  • Requisite= — como Requires=, mas a unidade listada deve já estar ativa; não tenta iniciá-la
  • BindsTo= — dependência bidirecional: se qualquer uma parar, a outra também para
  • After= — define apenas a ordem de inicialização, sem criar dependência de sucesso
  • Before= — o inverso de After=; esta unidade deve iniciar antes da listada
  • Conflicts= — esta unidade não pode coexistir com a listada; iniciar uma para a outra

Um erro comum é confundir After= com Requires=. Veja a diferença prática:

[Unit]
Description=Aplicação que depende do PostgreSQL
After=postgresql.service
Requires=postgresql.service

Sem o After=, mesmo com Requires=, o systemd poderia tentar iniciar os dois serviços em paralelo — e sua aplicação falharia porque o PostgreSQL ainda não estaria pronto. O After= garante a ordem; o Requires= garante que a dependência esteja ativa.

Para visualizar o grafo de dependências de um serviço:

systemctl list-dependencies nginx.service
nginx.service
● ├─system.slice
● ├─sysinit.target
● │ ├─dev-hugepages.mount
● │ ├─dev-mqueue.mount
● │ └─...
● └─network.target

Targets no systemd: substituindo os runlevels do SysV

Os targets são unidades de agrupamento que representam estados específicos do sistema, funcionando como os runlevels do SysV init, mas com muito mais flexibilidade. Diferente dos runlevels numerados (0 a 6), os targets têm nomes descritivos e podem ser compostos.

Correspondência entre targets e runlevels SysV:

  • poweroff.target — runlevel 0 (desligar)
  • rescue.target — runlevel 1 (modo single-user)
  • multi-user.target — runlevel 3 (multiusuário, sem interface gráfica)
  • graphical.target — runlevel 5 (multiusuário com interface gráfica)
  • reboot.target — runlevel 6 (reiniciar)

Para verificar o target padrão atual:

systemctl get-default
multi-user.target

Para alterar o target padrão permanentemente (por exemplo, em um servidor que não precisa de interface gráfica):

systemctl set-default multi-user.target

Para mudar o target ativo imediatamente sem reiniciar (equivalente ao antigo telinit):

systemctl isolate rescue.target

Atenção: o comando isolate encerra todos os serviços que não fazem parte do target de destino. Use com cuidado em servidores de produção, pois pode derrubar serviços ativos.

Você pode criar targets personalizados para agrupar serviços relacionados. Por exemplo, um target que representa o estado completo de uma aplicação:

[Unit]
Description=Stack completa da aplicação web
Requires=nginx.service postgresql.service redis.service
After=nginx.service postgresql.service redis.service

[Install]
WantedBy=multi-user.target

Salve como /etc/systemd/system/webapp.target e ative com systemctl enable webapp.target.

Criando e gerenciando um serviço systemd personalizado

Criar um serviço systemd do zero é uma habilidade fundamental para qualquer administrador de servidores Linux. O processo envolve escrever a unit file, recarregar o daemon e habilitar o serviço para iniciar automaticamente.

Vamos criar um serviço completo para uma aplicação Node.js hipotética, demonstrando as melhores práticas:

  1. Crie o arquivo de unidade em /etc/systemd/system/:
sudo nano /etc/systemd/system/nodeapp.service
  1. Adicione o conteúdo completo da unit file:
[Unit]
Description=Aplicação Node.js - API REST
Documentation=https://github.com/empresa/nodeapp
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=nodeapp
Group=nodeapp
WorkingDirectory=/opt/nodeapp
ExecStart=/usr/bin/node /opt/nodeapp/server.js
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=10s
StartLimitIntervalSec=60s
StartLimitBurst=3
StandardOutput=journal
StandardError=journal
SyslogIdentifier=nodeapp
Environment=NODE_ENV=production
Environment=PORT=3000
PrivateTmp=true
NoNewPrivileges=true
ProtectSystem=strict
ReadWritePaths=/opt/nodeapp/logs

[Install]
WantedBy=multi-user.target
  1. Recarregue o daemon do systemd para reconhecer o novo arquivo:
sudo systemctl daemon-reload
  1. Habilite o serviço para iniciar automaticamente no boot e inicie-o imediatamente:
sudo systemctl enable --now nodeapp.service
  1. Verifique o status do serviço:
sudo systemctl status nodeapp.service
● nodeapp.service - Aplicação Node.js - API REST
     Loaded: loaded (/etc/systemd/system/nodeapp.service; enabled; preset: enabled)
     Active: active (running) since Thu 2024-11-14 10:23:45 -03; 5s ago
   Main PID: 12345 (node)
      Tasks: 11 (limit: 4915)
     Memory: 45.2M
        CPU: 312ms
     CGroup: /system.slice/nodeapp.service
             └─12345 /usr/bin/node /opt/nodeapp/server.js

As diretivas de segurança PrivateTmp=true, NoNewPrivileges=true e ProtectSystem=strict são boas práticas que isolam o serviço do restante do sistema, reduzindo a superfície de ataque. Para servidores em produção, consulte também as Dicas de Otimização de Servidores Linux para complementar a configuração.

Usando o journalctl para diagnóstico de serviços

O journalctl é a interface de consulta ao journal do systemd, substituindo a leitura direta de arquivos de log dispersos. Ele oferece filtragem poderosa por unidade, tempo, prioridade e muito mais.

Comandos essenciais para diagnóstico:

journalctl -u nodeapp.service -n 50 --no-pager

Exibe as últimas 50 linhas de log do serviço especificado.

journalctl -u nodeapp.service -f

Segue o log em tempo real (equivalente ao tail -f).

journalctl -u nodeapp.service --since "2024-11-14 10:00:00" --until "2024-11-14 11:00:00"

Filtra logs por intervalo de tempo específico.

journalctl -u nodeapp.service -p err

Exibe apenas mensagens com prioridade de erro ou superior.

journalctl --disk-usage
Archived and active journals take up 1.2G in the file system.

Para limpar logs antigos e liberar espaço em disco:

sudo journalctl --vacuum-time=30d

Este comando remove entradas de log com mais de 30 dias. Ajuste o período conforme a política de retenção do seu servidor.

Sobrescrevendo configurações de unidades do sistema com drop-ins

Editar diretamente arquivos em /lib/systemd/system/ é uma prática ruim: atualizações de pacotes sobrescrevem suas mudanças. A solução correta é usar arquivos drop-in, que estendem ou sobrescrevem configurações sem modificar o arquivo original.

Para criar um drop-in para o serviço nginx:

sudo systemctl edit nginx.service

Este comando abre um editor e cria automaticamente o arquivo em /etc/systemd/system/nginx.service.d/override.conf. Adicione apenas as diretivas que deseja sobrescrever:

[Service]
LimitNOFILE=65536
Restart=always
RestartSec=3s

Após salvar, o systemd aplica as mudanças automaticamente. Para ver a configuração final mesclada:

systemctl cat nginx.service

O output mostrará o arquivo original seguido das sobreposições do drop-in, com comentários indicando a origem de cada seção.

Problemas comuns e como resolver

Sintoma: serviço entra em estado "failed" imediatamente após iniciar

Causa: O processo especificado em ExecStart= encerra com código de saída diferente de zero, ou o binário não existe no caminho especificado. O systemd interpreta qualquer saída não-zero como falha.
Solução: Execute systemctl status nome.service para ver o código de saída. Em seguida, use journalctl -u nome.service -n 30 para identificar a mensagem de erro exata. Verifique se o caminho do binário está correto com which nome-do-binario e se o usuário definido em User= tem permissão de execução.

Sintoma: alterações na unit file não têm efeito após reiniciar o serviço

Causa: O systemd mantém em cache as configurações das unidades. Simplesmente reiniciar o serviço com systemctl restart não relê o arquivo de configuração se o daemon não foi recarregado.
Solução: Sempre execute sudo systemctl daemon-reload após modificar qualquer arquivo de unidade. Depois, reinicie o serviço com sudo systemctl restart nome.service. Para confirmar que a nova configuração foi carregada, use systemctl cat nome.service.

Sintoma: serviço não inicia no boot mesmo após "systemctl enable"

Causa: A seção [Install] está ausente ou o valor de WantedBy= aponta para um target que não é o padrão do sistema. Sem a seção [Install], o systemctl enable não sabe onde criar o symlink de ativação.
Solução: Verifique se a seção [Install] existe e contém WantedBy=multi-user.target (para servidores sem interface gráfica). Confirme o target padrão com systemctl get-default. Após corrigir, execute daemon-reload, systemctl disable nome.service e systemctl enable nome.service novamente.

Sintoma: loop de reinicialização — serviço reinicia infinitamente

Causa: A combinação de Restart=always com StartLimitBurst e StartLimitIntervalSec mal configurada pode fazer o systemd entrar em loop ou, ao contrário, parar de tentar reiniciar antes do esperado.
Solução: Defina limites razoáveis: StartLimitIntervalSec=60s e StartLimitBurst=5 permitem até 5 reinicializações em 60 segundos antes de o systemd desistir. Para resetar o contador de falhas manualmente: sudo systemctl reset-failed nome.service. Investigue a causa raiz do crash antes de aumentar os limites.

Sintoma: "Failed to connect to bus: No such file or directory" ao usar systemctl

Causa: Este erro ocorre quando você tenta usar systemctl dentro de um container Docker ou chroot sem o systemd em execução. O systemd não é o PID 1 nesse ambiente.
Solução: Em containers Docker, use o gerenciador de processos nativo do container (como supervisord) ou utilize imagens baseadas em systemd para testes. Em ambientes chroot, monte o sistema de arquivos virtual antes: mount --bind /run /mnt/chroot/run.

Perguntas frequentes sobre systemd

O que é uma unit file no systemd e como ela funciona?

Uma unit file é um arquivo de configuração declarativo que descreve um recurso gerenciado pelo systemd, como um serviço, socket, timer ou ponto de montagem. Cada arquivo possui seções [Unit], [Service] (ou equivalente ao tipo) e [Install], onde você define comportamento, dependências e como o recurso deve ser iniciado. O systemd lê esses arquivos de /etc/systemd/system/ para personalizações do administrador e de /lib/systemd/system/ para os padrões instalados pelos pacotes do sistema, com o primeiro tendo prioridade.

Qual a diferença entre Wants= e Requires= no systemd?

Wants= define uma dependência fraca: se a unidade listada falhar ao iniciar, a unidade principal ainda continua executando normalmente. Requires= define uma dependência forte: se a unidade listada falhar ou for parada, a unidade principal também é interrompida imediatamente. Para a maioria dos serviços de aplicação, Wants= é preferível porque evita falhas em cascata desnecessárias — use Requires= apenas quando a dependência for absolutamente crítica para o funcionamento do serviço.

Como verificar por que um serviço systemd falhou ao iniciar?

Execute systemctl status nome-do-servico.service para ver o estado atual e as últimas linhas de log diretamente no terminal. Para um histórico completo de erros, use journalctl -u nome-do-servico.service -n 100 --no-pager. O campo Active mostrará failed com o código de saída do processo, e o log indicará a linha exata do erro — seja no processo em si, no arquivo de configuração ou em permissões de arquivo.

O que é um target no systemd e como ele substitui os runlevels do SysV?

Um target é uma unidade de agrupamento que representa um estado do sistema, equivalente aos runlevels numerados do SysV init, mas com nomes descritivos e maior flexibilidade de composição. Por exemplo, multi-user.target corresponde ao runlevel 3 (modo multiusuário sem interface gráfica) e graphical.target ao runlevel 5. Você pode alterar o target padrão com systemctl set-default nome.target e mudar o target ativo imediatamente com systemctl isolate nome.target, sem necessidade de reiniciar o sistema.

Como criar um serviço systemd que reinicia automaticamente após falha?

Na seção [Service] da unit file, defina Restart=on-failure para reiniciar apenas em caso de falha com código de saída não-zero, ou Restart=always para reiniciar em qualquer tipo de saída, incluindo saída limpa. Use RestartSec=5s para aguardar 5 segundos antes de tentar novamente, evitando loops rápidos que sobrecarregam o sistema. Após editar o arquivo, execute systemctl daemon-reload e systemctl enable --now nome.service para ativar as mudanças.

Conclusão

  • Domine a estrutura das unit files: compreender as seções [Unit], [Service] e [Install] e as diretivas de dependência (Wants=, Requires=, After=) é o fundamento para gerenciar qualquer serviço com confiança no Linux moderno.
  • Use drop-ins para personalizações: nunca edite arquivos em /lib/systemd/system/ diretamente; use systemctl edit para criar overrides que sobrevivem a atualizações de pacotes.
  • Combine journalctl com systemctl status: o diagnóstico eficiente de falhas depende de consultar o journal com filtros precisos de unidade, tempo e prioridade — isso reduz drasticamente o tempo de resolução de incidentes em produção.

Leia também

Precisa de ajuda com servidores Linux?

Configurar e manter serviços com systemd em produção exige um ambiente estável e com recursos adequados. Os planos de VPS da AviraHost oferecem servidores Linux com acesso root completo, suporte técnico especializado e infraestrutura otimizada para cargas de trabalho reais.

Conheça os planos de VPS Linux da AviraHost

  • 0 Os usuários acharam isso útil
  • systemd, Linux, serviços, AlmaLinux, AviraHost
Esta resposta foi útil?

Artigos Relacionados

Guia Completo: Como escolher o melhor plano de hospedagem para o seu site

Escolher o plano de hospedagem ideal para o seu site é fundamental para garantir seu bom...

Lista Prática: 5 Vantagens de ter SSL gratuito no seu site

Ter um certificado SSL no seu site não é apenas uma questão de segurança, mas também uma...

Comparativo: Hospedagem de sites vs. VPS: qual é a melhor opção?

Quando se trata de escolher entre hospedagem compartilhada ou VPS, as opções variam de acordo...

Dicas de Otimização de Servidores Linux

Dicas de Otimização de Servidores Linux Servidores Linux são amplamente utilizados por sua...

Como Implementar Soluções Eficientes para Melhorar a Gestão de Serviços Online

Como Implementar Soluções Eficientes para Melhorar a Gestão de Serviços Online...