Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

02 - Targets e Comparação com Runlevels

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

A transição da arquitetura do SysVinit para o systemd exigiu uma redefinição conceitual sobre como o estado do sistema operacional é representado e gerenciado. No SysVinit, o estado do sistema era rigidamente codificado através de uma abstração inteira linear chamada Runlevel. No systemd, o estado do sistema tornou-se uma ontologia flexível e composicional gerenciada por Unidades de Alvo (.target).

A substituição dos Runlevels estáticos por Targets dinâmicos aboliu a exclusão mútua de estados e permitiu a computação de dependências em paralelo no Grafo Acíclico Dirigido (DAG), acelerando significativamente a inicialização do espaço de usuário (user space) e garantindo determinismo na orquestração de serviços.


1. A Arquitetura Tradicional de Runlevels (SysVinit)

No padrão SysVinit (baseado na tradição System V UNIX), o processo PID 1 lia o arquivo /etc/inittab para determinar em qual Runlevel numérico a máquina deveria operar. Os Runlevels variavam formalmente de 0 a 6:

  • Runlevel 0: Desligamento do sistema (Halt / Shutdown).
  • Runlevel 1 / S: Modo Mono-usuário (Single-User / Rescue). Sem rede, sem daemons, apenas um shell root básico.
  • Runlevel 2: Modo Multi-usuário em texto sem suporte a rede (em distribuições derivadas de System V) ou idêntico ao 3 (em derivadas Debian).
  • Runlevel 3: Modo Multi-usuário completo com interface de linha de comando (CLI) e rede ativa (Console Multi-User).
  • Runlevel 4: Não utilizado / Reservado para parametrizações customizadas do administrador.
  • Runlevel 5: Modo Multi-usuário completo com rede e Gerenciador de Exibição Gráfica (Display Manager / GUI).
  • Runlevel 6: Reinicialização do sistema (Reboot).

Limitações Estruturais do Modelo de Runlevels

  1. Exclusão Mútua Rígida: O sistema só podia estar presente em um único Runlevel por vez. A transição do Runlevel 3 para o Runlevel 5 exigia a execução síncrona do script de troca, sem capacidade de composição modular.
  2. Sequenciamento Numérico Estático: As transições entre serviços dentro de um Runlevel dependiam do ordenamento lexicográfico de symlinks no diretório /etc/rcX.d/ (ex: S20network executava antes de S55sshd). Não havia verificação real de dependências em tempo de execução.
  3. Monolito de Execução: Mudar de estado significava parar sequencialmente um grupo de scripts com prefixo K (Kill) e iniciar sequencialmente outro grupo com prefixo S (Start).

2. A Ontologia dos Targets no Systemd

Uma unidade .target no systemd não é um contêiner de execução (não possui linhas ExecStart=), mas sim um ponto de consolidação lógica e sincronização. Os targets atuam como agrupadores de dependências declarativas (Wants=, Requires=, After=, Before=).

Diferente dos Runlevels, múltiplos targets podem estar ativos simultaneamente na RAM. Por exemplo, quando o servidor alcança o estado operacional com interface gráfica, o systemd mantém simultaneamente no estado active: basic.target, network.target, multi-user.target, e graphical.target.

O Grafo de Dependência do Systemd

A transição de estado no systemd ocorre pela resolução de um grafo onde os targets servem como marcos de conclusão (milestones).

                      +------------------+
                      |   poweroff.target| (Equivalente ao Runlevel 0)
                      +------------------+
                               ▲
                               │
                      +------------------+
                      |   graphical.target| (Equivalente ao Runlevel 5)
                      +------------------+
                               │
                               │ Requires/After
                               ▼
                      +------------------+
                      | multi-user.target| (Equivalente ao Runlevel 3)
                      +------------------+
                               │
                               │ Requires/After
                               ▼
                      +------------------+
                      |   basic.target   |
                      +------------------+
                               │
                               │ Requires/After
                               ▼
                      +------------------+
                      |  sysinit.target  |
                      +------------------+
                               │
                               │ Requires/After
                               ▼
                      +------------------+
                      |  rescue.target   | (Equivalente ao Runlevel 1)
                      +------------------+

  1. sysinit.target: Ponto de sincronização para inicialização básica do sistema de arquivos (montagem do /etc/fstab, inicialização de swap, aplicação de regras de sysctl, carga de chaves criptográficas e inicialização de dispositivos via udev).
  2. basic.target: Ponto onde os serviços fundamentais de runtime (como soquetes IPC D-Bus, paths de monitoramento, e temporizadores) foram satisfeitos.
  3. multi-user.target: Ponto onde todos os daemons de serviços de aplicação em linha de comando, serviços de rede e instâncias de login foram consolidados.
  4. graphical.target: Estende o multi-user.target adicionando o serviço do gerenciador de exibição gráfica (GDM, SDDM, LightDM).

3. Mapeamento de Equivalência: Runlevels vs. Targets

Para garantir compatibilidade com binários históricos e ferramentas do SysVinit, o systemd provê um mapeamento direto através de links simbólicos e codificação interna de unidades para os Runlevels legados:

Runlevel SysVinit Target Nativo do Systemd Arquivo de Unidade Descrição e Estado Resultante
Runlevel 0 poweroff.target poweroff.target Desliga e corta a alimentação da máquina via ACPI.
Runlevel 1 / S rescue.target rescue.target Isola o sistema em modo de emergência. Dispara o rescue.service (shell root).
Runlevel 2 multi-user.target runlevel2.target No systemd, runlevel2.target é um symlink para multi-user.target.
Runlevel 3 multi-user.target runlevel3.target Modo texto multi-usuário completo com rede ativa.
Runlevel 4 multi-user.target runlevel4.target Não utilizado por padrão; mapeado para multi-user.target.
Runlevel 5 graphical.target runlevel5.target Modo multi-usuário completo com interface gráfica ativa.
Runlevel 6 reboot.target reboot.target Encerra os processos e reinicia o hardware.
N/A emergency.target emergency.target Modo mínimo de recuperação (com raiz montada em ro, sem passar pelo sysinit.target).

Os arquivos de unidade de Runlevel estáticos (como /usr/lib/systemd/system/runlevel3.target) contêm apenas diretivas Alias= ou symlinks apontando para as unidades de target modernas, garantindo que invocações antigas como telinit 3 continuem funcionadas por redirecionamento de API.


4. Gerenciamento do Default Target (Alvo Padrão de Boot)

No SysVinit, a linha id:3:initdefault: dentro do /etc/inittab definia qual o Runlevel de inicialização da máquina. No systemd, esta configuração foi migrada para o sistema de arquivos através de um Link Simbólico Abstrato.

O arquivo /etc/systemd/system/default.target determina o alvo final que o PID 1 tentará alcançar durante o boot.

Inspecionando e Alterando o Target Padrão

Para consultar qual o alvo atualmente configurado como padrão de boot:

systemctl get-default

Para alterar o alvo padrão de inicialização em disco (por exemplo, mudando uma máquina de ambiente gráfico para servidor em linha de comando):

systemctl set-default multi-user.target

A Mecânica do set-default no Sistema de Arquivos:

A execução do comando systemctl set-default não altera bancos de dados opacos. O systemd realiza atomicamente a remoção e recriação do symlink em /etc/:

# Operação interna equivalente executada pelo systemctl:
ln -sf /usr/lib/systemd/system/multi-user.target /etc/systemd/system/default.target

No próximo ciclo de energização, o PID 1 lerá /etc/systemd/system/default.target, descobrirá que ele aponta para multi-user.target e montará o Grafo Acíclico Dirigido partindo dessa premissa.


5. O Mecanismo de Isolamento de Targets (systemctl isolate)

Uma das capacidades mais poderosas da arquitetura baseada em alvos é a transição dinâmica de estado do sistema em runtime através do mecanismo de Isolamento (Target Isolation).

O comando systemctl isolate <nome>.target simula a troca de Runlevel em tempo de execução sem requerer a reinicialização da máquina.

Requisitos Arquiteturais para o Isolamento

Nem todo .target pode ser isolado. Para que um alvo permita a execução da transição de isolamento, o seu arquivo de unidade deve conter explicitamente a diretiva booleana na seção [Unit]:

[Unit]
Description=Graphical Interface
Documentation=man:systemd.special(7)
Requires=multi-user.target
Wants=display-manager.service
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target
AllowIsolate=yes

Se a diretiva AllowIsolate=yes não estiver declarada, qualquer tentativa de executar systemctl isolate sobre a unidade será rejeitada pelo PID 1 com o erro: Target cannot be isolated.

A Lógica Interna da Transação de Isolamento

Ao invocar systemctl isolate graphical.target, o systemd processa a seguinte sequência de transição na memória:

  1. Computação do Grafo Alvo: O PID 1 calcula o conjunto completo de unidades que compõem a árvore de dependências do graphical.target.
  2. Cálculo da Delta de Unidades: O orquestrador compara as unidades atualmente em execução (active) com as unidades necessárias para o novo alvo.
  3. Parada das Unidades Desnecessárias: Todas as unidades ativas que não pertencem ao novo grafo do alvo isolado são imediatamente paradas. Por exemplo, se a máquina estava no emergency.target ou se havia serviços efêmeros ativos desvinculados do graphical.target, eles receberão sinais de encerramento (SIGTERM/SIGKILL).
  4. Ativação das Novas Unidades: As unidades necessárias pelo graphical.target que ainda não foram iniciadas são enfileiradas e disparadas em paralelo.

6. Targets Especiais de Manutenção e Recuperação

O systemd define dois targets primários para intervenção do administrador em cenários de degradação grave ou manutenção de baixo nível:

1. rescue.target (Modo de Resgate)

  • Equivalente ao antigo Runlevel 1 ou Single-User mode.
  • Encerra todos os serviços de rede, interfaces gráficas e daemons de aplicação.
  • Mantém os sistemas de arquivos locais montados em modo leitura-escrita (read-write).
  • Inicia o serviço rescue.service, que dispara o binário sulogin e solicita a senha do usuário root no console físico (TTY1).

2. emergency.target (Modo de Emergência)

  • O estado de isolamento mais drástico do sistema operacional.
  • Não tenta iniciar o sysinit.target ou montar os sistemas de arquivos declarados em /etc/fstab (exceto o sistema de arquivos raiz /, que permanece montado em modo somente leitura - read-only).
  • Nenhum daemon do espaço de usuário é iniciado.
  • Inicia o serviço emergency.service, fornecendo um shell de emergência imediato para reparos de tabela de partição, ajuste de arquivos /etc/fstab corrompidos ou recuperação do registro do journald.

Substituição de Target via Parâmetros de Kernel (Bootloader)

Se o sistema falhar em alcançar o default.target durante a inicialização devido a erros em serviços, o administrador pode sobrepor o alvo de inicialização diretamente no menu de edição do GRUB2, passando parâmetros na linha de comando do kernel:

  • Para forçar o boot em modo de resgate:
    systemd.unit=rescue.target
  • Para forçar o boot em modo de emergência:
    systemd.unit=emergency.target
  • Para passar o equivalente ao Runlevel 3 clássico:
    systemd.unit=multi-user.target ou simplesmente o argumento numérico 3.

O parâmetro systemd.unit= instrui o compilador do PID 1 a desconsiderar o arquivo /etc/systemd/system/default.target e construir o DAG de inicialização centrado estritamente no alvo fornecido no parâmetro de boot do kernel.