Depois de acompanharmos uma abordagem introdutória — porém bem detalhada — sobre o systemd e o conceito de sistemas de inicialização (system init), a jornada de conteúdos do tema continua. Desta vez, explicarei o que são os systemd runlevels (níveis de execução do systemd).
Também conhecidos como “modos de execução”, os runlevels não são frutos do conceito moderno inserido no systemd, visto que o seu uso remota de um tradicional antecessor: o sysvinit. Eles servem, basicamente, para determinar os serviços que inicializam com o sistema operacional Linux / Unix.
Se você é usuário do Windows, independentemente da versão, certamente já se deparou com uma série de opções de inicialização — as quais aparecerem quando o sistema é desligado de forma inadequada ou ocorrem falhas no boot. Alguns dos modos são:
- segurança;
- segurança com rede;
- segurança com prompt de comando; e
- depuração.
Essas alternativas de boot em sistemas Microsoft são conhecidas como níveis de inicialização. De certa maneira, podemos considerá-los equivalentes aos runlevels, mas com a diferença de que runlevel é voltado a sistemas baseados em Linux ou Unix, e oferecem mais flexibilidade para o usuário.
Acredito que a explicação acima tenha esclarecido mais claramente o assunto que tratarei neste artigo, não é mesmo? Então vou prosseguir com o texto apresentando, um a um, os systemd runlevels (e alguns conceitos indispensáveis). Mais adiante, apresento uma série de práticas bem legais de gerenciamento. Acompanhe!
Explorando mais a fundo o conceito de runlevel
Diferentemente de como ocorre nos sistemas MS Windows, os níveis de serviço do Linux, por exemplo, são representados por números. As classificações vão de 0 a 6, ou seja, existem sete configurações de boot diferentes para cada sistema operacional Linux-based. São eles:
- 0 – Halt: faz o desligamento seguro do computador;
- 1 – Single-User Mode: modo restrito a um só usuário (root) e sem rede;
- 2 – Multi-User Mode: permite que múltiplos usuários utilizem o sistema, sem rede;
- 3 – Multi-User Mode with Network: mesma regra que o antecessor, mas com rede;
- 4 – User-Definable: inicia o sistema carregando configurações definidas pelo usuário;
- 5 – X11: também conhecido como “Multiple user mode under GUI” ou “X”, é a inicialização do sistema com interface gráfica;
- 6 – Reboot: como o próprio nome já diz, reinicia o sistema.
Como descrito acima, os níveis “0” e “6”, embora façam parte dos runlevels, eles não estão ao alcance do usuário para uso do sistema com condições específicas. Somente podemos acioná-los no terminal para desligar ou reiniciar a máquina.
Já os demais, ordenados de 1 a 5, representam as possibilidades de inicialização que temos. Em qual deles o seu Linux está sendo executado no momento? Digite o comando runlevel no terminal para identificá-lo.
Variações dos systemd runlevels entre as principais distros
O padrão que mencionei acima não é, necessariamente, válido para todas as distribuições Linux. Projetos importantes, como Debian e Slackware, tem os níveis de serviço organizados de maneira diferente. Já as distribuições Fedora e SUSE, por exemplo, têm os runlevels exatamente como a explicação.
Se você estiver usando o Debian, saiba que os runlevels estão configurados da seguinte forma:
- 0 – Halt;
- 1 – Single-User Mode (minimal mode);
- 2 a 5 – Multi-User Modes; e
- 6 – Reboot.
O padrão do sistema Debian não diferencia os níveis entre 2 e 5, mas permite que o usuário os customize de acordo com as preferências. Assim como nas demais distribuições, o modo Single-User apenas carrega o mínimo de serviços; é comum utilizá-lo para fins de manutenção.
Assim como alguns sistemas operacionais têm peculiaridades nesse sentido, o systemd é ainda mais “radical”. No próximo tópico, veremos que, embora utilize o mesmo conceito de runlevels, no systemd o processo é um pouco diferente.
Conhecendo os systemd runlevels
Se você chegou a ler o artigo passado (do contrário, fica a recomendação), entendeu que o systemd é uma solução moderna que tem sido adotada em praticamente todas as distros do Linux. Por mais que ele remeta a sistemas de boot, na prática o programa vai muito além disso.
Por que estou retomando o assunto? Porque o modo como os runlevels são usados nos sistemas operacionais são baseados no sysvinit (ou Sys V Init, se preferir), que funciona a partir de scripts em shell. Embora compatível com os scripts do sysvinit, o systemd tem as suas particularidades.
Entre elas, cabe destacar os runlevels desse sistema — eles são os “novos runlevels”, propriamente. Nele, em vez de scripts, são acionadas unidades (units) chamadas Targets, que armazenam coleções de unidades que reúnem todas as configurações necessárias para iniciar determinados serviços junto com o sistema.
Supondo que o usuário tenha criado o próprio serviço de boot com o systemd. Isso significa que o sistema inicializará conforme as preferências do usuário, ou seja, carregará apenas serviços e processos que ele escolheu. Todas essas informações ficam guardadas na unidade Target.
Assim que o runlevel em questão é selecionado, o systemd puxa os parâmetros armazenados pela unidade Target correspondente ao runlevel, faz a leitura das instruções e as executa. Em suma, esse é o papel do Target.
Quais são os Targets que o systemd utiliza por padrão?
Enquanto você não criar o próprio serviço de boot — não se preocupe, ensino a fazê-lo no próximo tópico —, os runlevels do systemd serão carregados a partir das unidades Target padrões. Em outras palavras, unidades pré-configuradas que, em tese, englobam todos os serviços que o usuário comum necessita. São eles:
- poweroff.target: desliga o sistema e o computador (power off);
- rescue.target: aciona o modo rescue pelo shell;
- multi-user.target: configura o sistema para multiusuários sem interface gráfica;
- graphical.target: usa um sistema multiusuário com interface gráfica e serviços de rede; e
- reboot.target: desliga e reinicia o sistema.
Os systemd runlevels não são marcados por números, e sim por nomes acompanhados da extensão .target.
No entanto, é evidente a equivalência deles aos do systemvinit, de modo que o multi-user.target tem a mesma função dos níveis 2, 3 e 4, enquanto o graphical.target tem a função do runlevel 5 do sysvinit.
Para efeito de experimento, abra o terminal e digite o comando systemctl –type=service. Veja que é aberta uma imensa (provavelmente) lista de serviços em execução, contendo o status e a descrição de cada um; eles nada mais são que unidades de serviço presentes no graphical.target.
Há um serviço que você queira retirar do boot? Continue a leitura para aprender a fazer essa modificação.
Criando um serviço de boot com o systemd
Tendo você compreendido o mecanismo de boot do systemd e o papel da unidade Target nesse processo, agora vamos criar o nosso próprio nível de execução. Uma coisa muito legal que você descobrirá neste tópico é que o procedimento é muito mais fácil do que parece!
Primeiramente, vamos elaborar um breve cenário que servirá de base para a explicação.
Um usuário Linux deseja que um arquivo de script (script.sh, por exemplo) seja carregado automaticamente com o sistema operacional. Porém ele entende que a solução para isso é inserir o script na unidade Target correspondente ao runlevel desejado — no caso, a unidade multi-user.target.
Pensando única e somente no objetivo do usuário, vamos iniciar o processo digitando os seguintes comandos no terminal:
# cd /etc/systemd/system
# ls -l
O prompt retornará uma série de informações detalhadas referentes a arquivos e diretórios do systemd. Alguns deles, observe, têm uma espécie de indicador chamado “wants”, que simboliza o que o Target “multi-user” quer que seja carregado quando este runlevel for selecionado para o boot.
Criando um serviço no diretório do systemd
Sendo assim, se quisermos verificar os serviços que o multi-user.target deseja que sejam carregados automaticamente, temos de acessar o diretório /etc/systemd/system/multi-user.target.wants/, usando o comando, abaixo:
# ls multi-user.target.wants/
Novamente nos deparamos com uma lista, certo? Nela, podemos observar que tanto há elementos .service quanto .target. Isso é possível por um motivo simples: os Targets “armazenam” um conjunto de serviços, então eles pertencem a uma mesma classe de unidades.
Agora que acessamos o diretório, podemos criar um serviço a ser iniciado quando o runlevel Multi-User for acionado. Primeiro, criaremos uma unit: exemplo.service (logicamente, você pode modificar o nome e o conteúdo).
# vim exemplo.service
Em seguida, vamos escrever a configuração do arquivo conforme o exemplo:
[Unit] Description = executar script para atividade online After = network.target [Service] ExecStart = /root/scripts/script.sh [Install] WantedBy = multi-user.target
O que aconteceu aqui? Começamos descrevendo a função do serviço e a ordem em que ele será executado (após o serviço network.target). Na sequência, inserimos o diretório do arquivo e, em [Install], informamos que o serviço é válido para o runlevel multi-user.target.
Validando o processo
Já avançamos consideravelmente com a criação do nosso serviço. O que precisamos fazer agora é habilitá-lo e, em seguida, criar um script para ele. Comece digitando os comandos a seguir:
# systemctl enable connection.service
# ls multi-user.target.wants/
Note que o link para exemplo.service está presente na lista, o que significa que ele está pronto para execução no próximo boot. Tudo certo por aí também? Então vamos ao script:
# cd /root # mkdir scripts # cd scripts # vim script.sh
Dentro do arquivo, digite a linha conforme a instrução que você deseja. Exemplo:
#!/bin/bash ./script.sh
Por fim, torne o script executável usando o comando chmod +x script.sh. Vamos iniciar o serviço para testá-lo? Sem reiniciar o Linux, digite:
# systemctl start exemplo.service
Funcionou? Deixe um sinal nos comentários! Agora, vamos ver o que podemos fazer para modificar um nível de serviço.
Editando os Runlevels com o systemd
Modificar systemd runlevels é uma tarefa ainda mais fácil que a anterior. Mas por onde começar? Acho uma boa ideia descobrirmos qual é o runlevel que utilizamos por padrão. Digite:
systemctl get-default graphical.target
Traduzindo, o primeiro comando solicitou ao systemd que informasse o Target padrão (default.target). Como eu costumo usar o Linux pela interface gráfica para produzir os artigos do blog, o graphical.target é o runlevel padrão. Aliás, a menos que o usuário faça modificações, o default.target sempre será esse na maioria dos casos.
Retomando o exemplo do tópico anterior, é interessante que façamos a troca do runlevel padrão para o multi-user.target, pois ele executará o script que criamos há pouco. Faça isso da seguinte forma:
# systemctl set-default multi-user.target
Muito simples, não é mesmo? Outra possibilidade que considero bastante útil é a alternância de runlevels com o sistema operacional em execução. O resultado do procedimento é que somente os serviços que fazem parte do Target passarão a funcionar. Exemplo:
systemctl isolate multi-user.target
Fará com que o systemd execute o runlevel multi-user.target
systemctl isolate graphical.target
Retorna ao runlevel graphical.target
Observação: sempre que estiver mexendo com os runlevels, certifique-se de que nenhuma alteração cause problemas no seu Linux. Se possível, realize os testes numa máquina virtual usando o VirtualBox.
Usando o chkservice para gerenciar os serviços do systemd
Na maioria das vezes, o systemd é controlado a partir do utilitário systemctl, responsável por tarefas como: iniciar, reiniciar, parar, checar status, entre outras. Porém a tarefa de gerenciar os runlevels do systemd pode ser cansativa em função da quantidade de informações.
Um meio eficiente para simplificar o gerenciamento é a instalação do chkservice, uma ferramenta que categoriza as unidades (units) do systemd por serviços, targets, path e tudo mais, deixando-as organizadas em ordem alfabética.
Fora isso, ela nos permite executar ações por meio de atalhos do teclado, dispensando a necessidade de digitar linhas de comando. É uma facilidade que você, certamente, não quer dispensar, não é? Então use os comandos, abaixo, para fazer a instalação do chkservice no Debian:
$ sudo add-apt-repository ppa:linuxenko/chkservice $ sudo apt update $ sudo apt install chkservice
Pronto. Basta digitar sudo chkservice para dar start no programa! Para consultar os atalhos disponíveis, acrescente —help a este último comando.
10 Soluções para Problemas Comuns em Runlevels do Linux com Systemd
1. Serviço Não Inicia Automaticamente
Verifique se o serviço está habilitado para iniciar no boot:
sudo systemctl enable [serviço]
2. Serviço Falha ao Iniciar
Verifique os logs do serviço para identificar o problema:
sudo journalctl -u [serviço]
3. Rede Não Conecta no Boot
Certifique-se de que o serviço de rede está habilitado:
sudo systemctl enable NetworkManager.service
4. Partição Não Monta Automaticamente
Adicione a partição ao /etc/fstab
e verifique se o mount
está habilitado:
sudo systemctl enable systemd-fstab-generator
5. Alteração Permanente do Runlevel Padrão
Defina o target padrão do sistema:
sudo systemctl set-default multi-user.target
6. Mensagens de Erro ao Iniciar Serviços
Verifique os logs do Systemd:
sudo journalctl -xe
7. Problemas com Serviços Dependentes
Certifique-se de que os serviços dependentes estão configurados corretamente nos arquivos de unidade:
[Unit]
Requires=[serviço_dependente]
After=[serviço_dependente]
8. Logs de Serviços Incompletos
Aumente o nível de verbosidade dos logs:
sudo systemctl set-log-level debug
9. Serviços Lentos para Iniciar
Identifique e otimize serviços que demoram para iniciar:
systemd-analyze blame
10. Falhas ao Desligar ou Reiniciar o Sistema
Verifique os serviços que podem estar causando a falha:
systemctl list-jobs
Resumindo, neste artigo sobre systemd runlevels (complementar à introdução ao sistema) procurei explicar o mais claramente possível o conceito de runlevels e como ele é aplicado no systemd. Em seguida, elenquei alguns procedimentos fundamentais de gerenciamento que o permitirá controlar os serviços de boot no Linux.
Quer dominar o Linux mais rapidamente e progredir na sua carreira em TI? Não perca tempo: garanta acesso à sua aula grátis do curso Profissionais Linux!