Entendendo os Targets do Systemd: Conceitos Essenciais Explicados
Entenda os targets do systemd, targets de inicialização padrão, mapeamentos de runlevels, isolamento, targets personalizados e comandos de solução de problemas.
Entendendo os Targets do Systemd: Conceitos Essenciais Explicados
Os targets do systemd são mais fáceis de entender se você parar de pensar neles como serviços. Um serviço inicia um processo. Um target agrupa unidades em um estado nomeado do sistema. Quando uma máquina inicializa para multi-user.target, o systemd não está iniciando um programa chamado "multi-user". Ele está tentando atingir um estado onde as unidades desejadas por aquele target foram iniciadas ou pelo menos tiveram suas tentativas de início realizadas.
Essa distinção ajuda quando você está depurando problemas de inicialização. Se graphical.target está lento, o target em si raramente é o problema. Uma das unidades de exibição, login, rede, montagem ou aplicativo puxadas para aquele target está lenta ou falhando. Os targets fornecem o mapa.
O que são Targets do Systemd?
No ecossistema systemd, um target é um tipo especial de arquivo de unidade (como arquivos .service ou .socket) que serve a um propósito organizacional crítico. Ao contrário das unidades de serviço que definem como iniciar ou parar um processo específico, as unidades de target definem um estado do sistema ou uma coleção de unidades que devem estar ativas juntas. Elas atuam como pontos de agrupamento lógico e pontos de sincronização para outras unidades do systemd.
Pense nos targets como marcos na jornada operacional do sistema. Quando o systemd inicializa, ele não apenas lança uma lista de serviços arbitrariamente; ele trabalha para atingir um target específico. Este target, por sua vez, puxa todos os serviços, sockets, pontos de montagem e outros targets necessários para que esse estado seja alcançado. Esta abordagem orientada por dependências garante um processo de inicialização previsível e eficiente.
Para aqueles familiarizados com sistemas init Linux mais antigos como SysVinit, os targets do systemd são o equivalente moderno dos runlevels. Enquanto o SysVinit tinha um conjunto fixo de runlevels (por exemplo, runlevel 3 para modo texto multiusuário, runlevel 5 para modo gráfico multiusuário), os targets do systemd são mais flexíveis. Eles são nomeados, não numerados, e você pode definir targets personalizados, oferecendo maior granularidade e extensibilidade.
Como os Targets Funcionam: Agrupamento e Dependências
Os targets alcançam suas capacidades de agrupamento e definição de estado através de dependências explícitas definidas em seus arquivos de unidade. As diretivas primárias usadas para isso são Wants=, Requires=, After= e Before=.
Wants=: Especifica dependências "fracas". Setarget AWants=unidade B, o systemd tentará iniciarunidade Bquandotarget Afor ativado. No entanto,target Aainda será iniciado mesmo seunidade Bfalhar ao iniciar. Isso é comumente usado para agrupar serviços relacionados que são desejáveis, mas não estritamente essenciais.Requires=: Especifica dependências "fortes". Setarget ARequires=unidade B, entãounidade Bdeve ser iniciada com sucesso para quetarget Aative. Seunidade Bfalhar,target Atambém falhará ou não iniciará. Isso é usado para dependências críticas.After=: Define uma dependência de ordenação. Setarget AtemAfter=unidade B, entãotarget Asó iniciará apósunidade Bter iniciado. Isso não implica uma dependência de sucesso, apenas de ordem.Before=: O inverso deAfter=. Setarget AtemBefore=unidade B, entãounidade Bsó iniciará apóstarget Ater iniciado.Conflicts=: Garante que certas unidades não estejam ativas simultaneamente. Setarget AConflicts=unidade B, então ativartarget Airá pararunidade Bse estiver em execução, e vice-versa.
Essas diretivas permitem que os targets atuem como orquestradores robustos, puxando serviços e outros targets conforme necessário, e definindo a ordem em que devem iniciar. Por exemplo, multi-user.target tipicamente Wants= network.target e vários outros serviços, garantindo que estejam ativos quando o sistema atingir um estado multiusuário.
Você pode inspecionar o conteúdo de um arquivo de unidade de target para ver suas dependências:
systemctl cat multi-user.target
Este comando exibirá o conteúdo do arquivo de unidade multi-user.target, mostrando sua Description, Documentation e, crucialmente, suas diretivas Wants=, Requires=, After= e outras que definem o que constitui o estado multiusuário.
Targets Comuns do Systemd Explicados
O systemd fornece uma variedade de targets predefinidos, cada um correspondendo a um estado ou funcionalidade específica do sistema. Compreendê-los é crucial para a administração do sistema:
default.target: Este é o target mais importante, pois define o estado padrão no qual seu sistema será inicializado. Geralmente é um link simbólico paragraphical.target(para desktops) oumulti-user.target(para servidores).graphical.target: Este target é tipicamente usado para sistemas com um ambiente de desktop gráfico. Ele puxamulti-user.targete então adiciona serviços necessários para o gerenciador de login gráfico e servidor de exibição (por exemplo, GDM, LightDM, Xorg, Wayland).multi-user.target: Este é o estado padrão para sistemas multiusuário sem uma interface gráfica. É comum para servidores e fornece todos os serviços necessários para acesso via linha de comando, rede e a maioria das operações de daemon.basic.target: Um estado mínimo que inclui serviços básicos do sistema necessários para operações fundamentais, mas antes demulti-user.target. Ele tipicamente puxasysinit.targete outros serviços essenciais.sysinit.target: Este target é alcançado muito cedo no processo de inicialização. É responsável por tarefas de inicialização do núcleo do sistema, como montar sistemas de arquivos/etc/fstab(excluindo remotos), configurar swap e outras inicializações relacionadas a hardware.local-fs.target: Garante que todos os sistemas de arquivos locais especificados em/etc/fstabestejam montados.remote-fs.target: Garante que todos os sistemas de arquivos remotos (por exemplo, NFS, CIFS) especificados em/etc/fstabestejam montados.network.target: Indica que a conectividade básica de rede está disponível (por exemplo, interfaces de rede estão ativas). Não garante conectividade total com a internet ou atribuição de endereço IP.network-online.target: Um ponto de sincronização para serviços que desejam esperar até que o gerenciador de rede considere a rede online. Não prova que a internet, DNS ou uma API remota estão acessíveis, e só funciona como esperado quando o serviço wait-online relevante está habilitado.rescue.target: Fornece um shell de usuário único com serviços mínimos em execução e sistemas de arquivos locais montados. Útil para recuperação do sistema e solução de problemas.emergency.target: Um ambiente ainda mais mínimo querescue.target. Fornece um shell no sistema de arquivos raiz, que é tipicamente montado como somente leitura. Nenhum outro serviço é iniciado. Para situações críticas de emergência.poweroff.target,reboot.target,halt.target: Estes targets são usados para desligar, reiniciar ou parar o sistema, respectivamente. Quando ativados, eles param a maioria dos serviços e preparam o sistema para o estado de energia desejado.
Gerenciando Targets do Systemd
Interagir com targets do systemd envolve principalmente o utilitário de linha de comando systemctl.
Visualizando Targets Ativos e Padrão
Para ver em qual target seu sistema está atualmente em execução:
systemctl get-default
Para listar todas as unidades de target atualmente carregadas:
systemctl list-units --type=target
Este comando mostra targets ativos, carregados e estáticos, juntamente com suas descrições.
Alterando o Target de Inicialização Padrão
Você pode alterar o target no qual seu sistema inicializa por padrão. Por exemplo, para definir multi-user.target como padrão:
sudo systemctl set-default multi-user.target
Para reverter para graphical.target:
sudo systemctl set-default graphical.target
Este comando cria um link simbólico de /etc/systemd/system/default.target para o arquivo de target desejado.
Inicializando em um Target Diferente Temporariamente
Às vezes você precisa inicializar em um target específico apenas uma vez (por exemplo, para solução de problemas). Você pode conseguir isso anexando um parâmetro do kernel durante a inicialização. Quando o menu de inicialização GRUB aparecer, edite a entrada de inicialização (geralmente pressionando e) e adicione systemd.unit=nome_do_target.target à linha de comando do kernel.
Por exemplo, para inicializar no modo de resgate:
systemd.unit=rescue.target
Alternando Targets Durante a Execução
Você pode alternar para um target diferente enquanto o sistema está em execução usando o comando systemctl isolate. Este comando irá parar todos os serviços não exigidos pelo novo target e iniciar todos os serviços exigidos por ele.
Aviso: Usar systemctl isolate pode interromper a operação do seu sistema, especialmente se você alternar para um target de nível muito inferior, como multi-user.target a partir de graphical.target em uma máquina desktop. Use com cautela.
Para alternar de graphical.target para multi-user.target:
sudo systemctl isolate multi-user.target
Para voltar para graphical.target (assumindo que era o estado anterior):
sudo systemctl isolate graphical.target
Criando Targets Personalizados
Embora o systemd forneça muitos targets úteis, você pode encontrar situações onde criar um target personalizado é benéfico. Isso é particularmente verdadeiro para implantações de aplicativos complexos onde você precisa agrupar vários serviços que devem sempre iniciar e parar juntos, ou para definir um ambiente específico para seu aplicativo.
Para criar um target personalizado:
- Crie um arquivo
.target: Coloque-o em/etc/systemd/system/. Por exemplo,my-application.target.# /etc/systemd/system/my-application.target [Unit] Description=Meu Target de Aplicativo Personalizado Wants=my-database.service my-webserver.service After=my-database.service my-webserver.serviceDescription: Uma descrição legível por humanos.Wants=: Liste os serviços ou outros targets que este target deve puxar.After=: Defina a ordem. O target iniciará após estas unidades.
- Crie os serviços: Certifique-se de que
my-database.serviceemy-webserver.service(ou quaisquer serviços que você listar) existam e estejam configurados corretamente. - Recarregue o systemd: Informe o systemd sobre o novo arquivo de unidade.
sudo systemctl daemon-reload
4. **Habilite e Inicie**: Agora você pode habilitar e iniciar seu target personalizado, que por sua vez iniciará seus serviços desejados. bash
sudo systemctl enable my-application.target
sudo systemctl start my-application.target
```
Isso permite que você gerencie um grupo de serviços relacionados como uma única unidade lógica, simplificando implantações de aplicativos complexos.
Runlevels e Targets Sem Rodeios
Se você veio do SysVinit, o mapeamento aproximado é:
| Ideia antiga de runlevel | Target comum do systemd |
|---|---|
| Modo de reparo de usuário único | rescue.target |
| Modo texto multiusuário | multi-user.target |
| Modo gráfico multiusuário | graphical.target |
| Reinicializar | reboot.target |
| Desligar | poweroff.target |
Trate isso como um auxílio de tradução, não um modelo perfeito. Os runlevels SysV eram um pequeno conjunto fixo de estados numerados. Os targets do systemd são unidades nomeadas com dependências, e pode haver muitos deles. Um pacote pode instalar seu próprio target. Você pode criar um para um fluxo de trabalho de implantação. Alguns targets são feitos para serem isolados; outros são apenas pontos de agrupamento usados durante a inicialização.
Você pode ver quais targets permitem isolamento com:
systemctl show multi-user.target -p AllowIsolate
systemctl show basic.target -p AllowIsolate
Isso é importante porque systemctl isolate não é um comando inofensivo de "alternar visualização". Ele para unidades que não fazem parte da transação do novo target. Em um desktop, isolar multi-user.target geralmente irá parar a sessão gráfica. Em um servidor remoto, isolar o target errado pode parar os serviços de rede ou login e bloquear seu acesso.
Como os Serviços se Tornam Parte de um Target
A maior parte da associação de target no dia a dia vem da seção [Install] de um arquivo de serviço:
[Install]
WantedBy=multi-user.target
Quando você executa:
sudo systemctl enable myapp.service
systemd cria um link simbólico sob um diretório como:
/etc/systemd/system/multi-user.target.wants/myapp.service
Esse link simbólico é o que faz multi-user.target querer o serviço durante a inicialização. O arquivo de serviço pode existir e ser perfeitamente válido sem estar habilitado. Nesse caso, iniciar multi-user.target não o puxará automaticamente.
É por isso que systemctl start myapp.service e systemctl enable myapp.service resolvem problemas diferentes. start executa agora. enable o conecta a um target de inicialização futuro. enable --now faz ambos.
Para verificar se um serviço está habilitado para um target:
systemctl is-enabled myapp.service
systemctl list-dependencies multi-user.target | grep myapp
Se um serviço inicia manualmente, mas não na inicialização, esta é uma das primeiras coisas a verificar.
Um Pequeno Target Personalizado Que É Realmente Útil
Targets personalizados são mais úteis quando fornecem aos operadores um comando para um grupo de unidades relacionadas. Imagine uma pilha de aplicativos simples:
app-api.service
app-worker.service
app-scheduler.service
Você pode criar:
# /etc/systemd/system/app-stack.target
[Unit]
Description=Pilha de aplicativos
Wants=app-api.service app-worker.service app-scheduler.service
After=network-online.target
Wants=network-online.target
AllowIsolate=no
Em seguida, adicione cada serviço ao target:
[Install]
WantedBy=app-stack.target
Após daemon-reload, habilite os serviços ou o target dependendo do comportamento desejado:
sudo systemctl daemon-reload
sudo systemctl enable app-api.service app-worker.service app-scheduler.service
sudo systemctl start app-stack.target
Isso fornece um agrupamento legível sem fingir que o target é um supervisor de processo. Se app-worker.service falhar, inspecione esse serviço. O target é apenas o ponto de agrupamento.
Se você quiser que parar o target pare todos os serviços da pilha, adicione PartOf=app-stack.target a cada serviço:
[Unit]
PartOf=app-stack.target
Agora systemctl stop app-stack.target se propaga para os serviços membros. Essa é frequentemente a peça que falta em exemplos de targets personalizados.
Solução de Problemas com Targets
Targets também são inestimáveis para solucionar problemas de inicialização ou falhas de serviço:
- Identificando dependências: Se um serviço falhar ao iniciar, inspecionar o target ao qual ele pertence pode revelar dependências ausentes ou com falha. Use
systemctl status <nome_do_serviço>esystemctl list-dependencies <nome_do_target>. - Inicialize em targets mínimos: Se seu sistema falhar ao inicializar em
graphical.targetoumulti-user.target, tente inicializar emrescue.targetouemergency.targetusando o método de parâmetro do kernel. Isso fornece um ambiente mínimo onde você pode diagnosticar problemas sem a complexidade de muitos serviços em execução. - Verifique os logs: Após tentar iniciar um target ou um serviço, sempre verifique os logs do
journalctlpara erros:journalctl -b -u <nome_do_target_ou_serviço>
Melhores Práticas e Dicas
- Use
network-online.targetcom cuidado: Se seu serviço precisar de configuração de rede antes da inicialização, combineAfter=network-online.targetcomWants=network-online.targete confirme se a unidade wait-online apropriada está habilitada. Ainda mantenha a lógica de repetição no aplicativo para dependências remotas. - Entenda a ordem de inicialização: Familiarize-se com o fluxo geral de
sysinit.targetparabasic.target, depoismulti-user.target/graphical.target. Isso ajuda na depuração de serviços que falham no início do processo de inicialização. - Seja cauteloso com
default.target: Alterardefault.targetpode alterar significativamente o comportamento de inicialização do seu sistema. Sempre teste configurações personalizadas em um ambiente que não seja de produção primeiro. - Use
Wants=para dependências não críticas: Para serviços que são úteis, mas não estritamente necessários para que um target seja considerado "ativo", useWants=em vez deRequires=. Isso evita que uma única falha de serviço opcional se propague e impeça a ativação de todo o target.
O Modelo Mental a Manter
Um target é um estado nomeado, não um daemon. default.target decide o destino normal de inicialização. multi-user.target é o estado usual do servidor. graphical.target adiciona a pilha de exibição. rescue.target e emergency.target são ferramentas de reparo. Targets personalizados são ferramentas de agrupamento quando tornam as operações mais claras.
Quando algo relacionado a target quebrar, evite culpar o target primeiro. Pergunte qual unidade foi puxada, qual regra de ordenação a atrasou e qual dependência falhou. systemctl cat, systemctl list-dependencies, systemctl show e journalctl -b geralmente responderão a essas perguntas mais rápido do que ler diagramas genéricos de inicialização.