Aula #4 - init: SystemV, Upstart, Systemd


Quando um sistema Linux é iniciado, muitas tarefas têm de ser realizadas de forma cooperativa. 
Os dispositivos têm de ser reconhecido e inicializado, serviços do sistema têm de ser carregados, sistemas de arquivos devem ser disponibilizados, processos importantes de gestão tem que iniciar e o sistema deve atingir um estado que permita aos usuários fazer login. 
Tudo isto tem que ser feito na sequência correta e tão rapidamente quanto possível. 




O processo INIT:

 /sbin/init (Normalmente chamado apenas de init) é o primeiro processo da camada do usuário executado no sistema, e ele continua a ser executado até que o sistema seja encerrado. Tradicionalmente, é considerado o pai de todos os processos, embora tecnicamente isso não seja mais verdade já que alguns processos são iniciados diretamente pelo kernel.

O init coordena as fases posteriores do processo de inicialização, configura todos os aspectos do ambiente e inicia os processos necessários para fazer o login no sistema. O init também trabalha em estreita colaboração com o kernel fazendo limpeza quando processos terminam.

Tradicionalmente, quase todas as distribuições baseavam o init no venerável SysVinit do UNIX. 


No entanto, este sistema foi desenvolvido décadas atrás em circunstâncias bastante diferentes:


  •     O alvo era sistemas multi-usuários de mainframe (e não computadores pessoais, laptops e outros dispositivos).
  •     O alvo era um sistema de processador único.
  •     Tempos de inicialização e desligamento não era uma questão importante;


A inicialização era vista como um processo sequencial. Cada etapa necessária era concluída antes da próxima começar. 
Assim, a inicialização não podia tirar proveito do processamento paralelo oferecida pela disponibilidade de vários processadores no sistema.


Em segundo lugar, o desligamento e reboot eram vistos como eventos relativamente raros e a duração não era considerada importante.

Para lidar com as limitações impostas pelo SysVinit, novos métodos de iniciar o sistema foram desenvolvidos. Enquanto existem outros métodos, dois foram os principais adotados por distribuições Enterprise:



  • Upstart
Upstart foi desenvolvido pelo Ubuntu e veio com o release 6.10 em 2006, e se tornou o padrão no release  9.10 em 2009. Também foi adotado pelo Fedora 9 (em 2008) e pelo RHEL 6 e seus clones, como o CentOS, Scientific Linux e o Oracle Linux, e também no openSUSE é oferecido como opção desde a versão 11.3. Também é popular em distribuições para embarcados.  
  • Systemd
Systemd é mais recente e o Fedora foi a primeira distribuição a adotá-lo em 2011.
O RHEL 7 é baseado no systemd e todas as principais distribuições Linux adotaram o systemd como padrão ou anunciaram que vão fazê-lo. Os principais desenvolvedores do systemd são próximos da comunidade do kernel do Linux. Até o Ubuntu trocou o Upstart em favor do systemd.



A migração para novidades pode ser complicada e bugs e funcionalidades em falta podem ser muito ruins, por isso existem camadas compatibilidade. Assim, utilitários e métodos SysVinit continuam funcionando, mesmo que o sistema de inicialização tenha sido alterado drasticamente.

A história de tudo isso e as controvérsias são bastante complicadas, e personalidades coloridas têm garantido que nem toda a discussão seja de natureza técnica. Em nosso contexto, não vamos ver por esta perspectiva.



Vamos se concentrar no SysVinit e systemd com uma breve introdução ao Upstart. (Mesmo que o RHEL 6 e algumas outras distribuições usem o Upstart ele foi bem escondido em camas de compatibilidade para as ferramentas do SysVinit).




Rulevels

Quando um sistema usando o SysVinit inicia, ele passa por uma sequencia de runlevels que definem diferentes estados do sistema; eles são numerados de 0 a 6.


O Runlevel 0 é reservado para o estado system halt(desligar) , o runlevel 1 é para o modo monousuário, e o runlevel 6 é para reiniciar o sistema. Os outros runlevels são usados para definir quais serviços serão executados para um sistema geral e distribuições diferentes definem o significado de cara runlevel arbitrariamente. Por exemplo, em sistemas baseados em Red Hat, o runlevel 2 é definido como sistema rodando sem rede e sem ambiente gráfico, enquanto o runlevel 3 inclui rede, e o runlevel 5 inclui o ambiente gráfico.

O runlevel atual pode ser exibido com o comando runlevel como em:

$ runlevel
N 5

Onde o primeiro caractere é o nível anterior; N significa desconhecido.

telinit pode ser usado para alterar o nível de execução do sistema. Por exemplo, para ir do runlevel 3 para o 5:

$ sudo /sbin/telinit 5



Runlevels do Sistema

Runlevel    Meaning
S,s             Mesmo que 1
0               Faz o processo de Shutdown do sistema e desliga a energia
1               Modo monousuário(Single User Mode)
2               Multiusuário, sem NFS, apenas modo texto
3               Multiusuário, com rede e NFS, modo texto
4               Não usado
5               Multiusuário, com rede e NFS, modo gráfico
6               Reboot



Quando o processo init inicia, a primeira tarefa que ele realiza é ler o arquivo /etc/inittab. Historicamente este arquivo dizia ao init quais scripts executar para iniciar o sistema em cada runlevel, com um linha para cada runlevel:


id:runlevel(s):action:process


em que:


  •     id: uma identificação única de 1-4 letras.
  •     runlevel(s): zero ou mais caracteres únicos indicando em quais runlevels as ações devem ser executadas.
  •     action: descrição da ação.
  •     process: especifica o processo a ser executado.


No entanto, em sistemas mais recentes, como o RHEL 6 o upstart é escondido atrás de uma camada de compatibilidade, e a única linha não comentada neste arquivo é o nível de execução padrão:


id:5:initdefault


Este é o nível alvo ao iniciar o sistema. No entanto se outro valor for passado na linha de comando do kernel, o init ignora o conteúdo do arquivo. (Passar o runlevel na linha de comando do kernel é feito adicionando o número do runlevel no final da linha de comando) O padrão é 5 para iniciar a rede e o ambiente gráfico, ou 3 para um servidor com rede mas sem ambiente gráfico.




SysVinit


O método tradicional é rodar primeiro o script rc.sysinit, que executa várias tarefas, como iniciar o LVM, montar sistemas de arquivo, etc. 
Este script fica na pasta /etc mas o mais provável é encontrá-lo em /etc/rc.d com um link simbólico para /etc.

Em seguida, o script rc (na mesma pasta) é executado com o runlevel alvo como argumento. 
Isso faz com que o sistema vá na pasta rc.d/rc[0-6].d e rode todos os scripts localizados na pasta, como em:



$ ls -lF /etc/rc.d/rc5.d




O script rc.local  pode ser usado para iniciar aplicações específicas do sistema local.



Observer que:

    Na verdade todos os scripts estão na pasta /etc/init.d: os diretórios de cada runlevel contém apenas links simbólicos para esta pasta.



  •     Scripts que devem ser Iniciados(Start) começam com a letra S no nome.


  •     Scripts que devem ser Terminados (Kill) começam com K no nome.


A existência ou a não existência de um link em um diretório de runlevel determina se o script será executado naquele runlevel.


O número que aparece após o K or S no nome de cada script determina a ordem de execução dos scripts. O nome do script é também o nome do service.

Controla quais serviços são executados em cada runlevel é apenas uma questão de gerenciar links simbólicos. Enquanto é possível fazer a gestão manualmente, existem ferramentas como o chkconfig que foi feito para simplificar esta tarefa.





chkconfig

O chkconfig é usado para verificar e configurar quais serviços serão executados em cada runlevel do sistema. 

Exemplos do chkconfig

    Verificar se um serviço está configurado para iniciar no runlevel atual:

    $ chkconfig some_service

    Vai retornar se o serviço deve ser iniciado ou não com a inicialização do sistema. Lembre-se de que uma resposta positiva não indica que o serviço está rodando, indica apenas que ele deveria ter sido iniciado junto com o servidor.


    Ver quais serviços são iniciados em quais runlevels:

    $ chkconfig --list [service names]



    Liga um serviço para ser iniciado no próximo boot:

    $ sudo chkconfig some_service on


    Não inicia um serviço no próximo boot:



​    $ chkconfig some_service off



    Lembre-se que para iniciar e parar serviço agora você deve usar:


    $ sudo service some_service [ stop | start ]



  Não é difícil adicionar seus próprios serviços e escrever seus próprios scripts de inicialização. 
Basta colocar o script em /etc/init.d com o formato correto(apenas algumas linhas no topo!) 
 E, em seguida, usar chkconfig --add para ativar ou chkconfig --del para desativar a capacidade de interagir com o seu novo serviço com as ferramentas padrão do sistema como o próprio chkconfig.
 

Como o chkconfig determina qual número deve aparecer após o S ou o K em um link simbólico, e como ele sabe quais runlevels ligar e desligar? 

A informação está nos próprios scripts, que contém uma linha no topo similar a:



# chkconfig: 2345 10 90



O primeiro argumento depois de chkconfig:   determina em quais runlevels o serviço deve ser ligado por padrão. O exemplo determina os runlevels 2, 3, 4 and 5.



O segundo e terceiro número são prefixos numéricos nos scripts de partida (start) e parada (stop), então no exemplo eles começam com S10 e K90





Service


Todo sistema operacional tem serviços que são normalmente carregados quando o sistema é iniciado e que permanecem em execução até o o sistema ser desligado. Estes serviços podem ser iniciados, parados, ou reiniciados a qualquer momento, o que normalmente necessita privilégios do root. Em um sistema Linux rodando ou emulando o SysVinit, os serviços são aqueles localizados na pasta /etc/init.d.

Você pode ver o estado atual de um serviço específico com:



    $ sudo service network status

    Configured devices:
    lo eth0 eth1 eth2 wlan0
    Currently active devices:
    lo eth0




   $ sudo service openvpn status
   VPN 'server' is running

   
   
service recebe série de opções, que variam de acordo com o serviço particular; por exemplo:


$ sudo service network

Usage: /etc/init.d/network {start|stop|restart|reload|status}



$ sudo service iptables

Usage: /etc/init.d/iptables {start|stop|restart|condrestart|status|panic|save}



A ferramenta service apenas muda para o diretório /etc/init.d e executa o script com as opções fornecidas.

Você pode ver o status de todos os serviços no sistema com:

        $ sudo service --status-all
       
       
Iniciar e parar serviços com o comando service só tem efeito imediato no sistema; todas as alterações são perdidas na próxima vez que o sistema for reiniciado. 
Para fazer com que um serviço seja iniciado e para fazer com que um serviço não seja iniciado na inicialização do sistema, distribuições baseadas no Linux da Red Hat usam o aplicativo chkconfig como descrito anteriormente.


Em sistemas Debian incluíndo o Ubuntu os utilitários listados dependem de ter os pacotes sysvinit-utils e chkconfig instalados:

$ sudo apt-get install sysvinit-utils chkconfig


No entanto, as versões recentes do Ubuntu não empacotam o chkconfig; você vai tem que usar o utilitário update-rc.d.


Como alternativa, você pode usar os comandos mais nativos nesses sistemas. Por exemplo, o equivalente da ferramenta service é:

$ sudo invoke-rc.d cups [ status | start | stop ]



$ sudo status cups


para verificar ou mudar o estado do cups. 
O comando status é mais recente e deve ser usado ao invés do invoke-rc.d. Da mesma forma o equivalente do chkconfig seria:


$ sudo update-rc.d cups [ defaults | purge ]

$ sudo sysv-rc-conf cups [ on | off ]



Você terá que consultar man pages para a documentação completa.




Upstart


O Upstart é orientado a eventos, ao invés de uma sequencia de procedimentos executados em série. Notificações de eventos são enviados ao processo init solicitando a execução de comandos em momentos específicos após os pré-requisitos terem sido atendidos. 
Como o Upstart está sendo substituído pelo systemd, não vamos dedicar muito tempo, nem muitos exercícios com ele.

Os arquivos de configuração do upstart são:
  •   /etc/init/rcS.conf
  •  /etc/rc-sysinit.conf
  •  /etc/inittab
  •  /etc/init/rc.conf
  •  /etc/rc[0-6].d

 Quando o kernel inicia o processo init isso faz com que o script rcS.conf seja executado, que por sua vez executa o script rc-sysinit.conf.

O rc-sysinit.conf vai fazer várias tarefas, incluindo iniciar o LVM, montar sistemas de arquivos, para então executar os scripts de inicialização dos runlevel especificado no arquivo /etc/inittab.

Isso é feito executando o rc.conf e passando o runlevel como parâmetro. Estes scripts são responsáveis por iniciar todos os serviços do sistema.

Como mencionado anteriormente, o /etc/inittab é obsoleto, e é apenas usado para configurar o runlevel padrão pela linha initdefault . 
Outras configurações são feitas por jobs do  Upstart na pasta /etc/init. Geralmente, eventos do  Upstart podem ser encontrados na pasta /etc/event.d .


Por exemplo o número de consoles tty ativos é definido pela variável ACTIVE_CONSOLES no arquivo /etc/sysconfig/init, que é lido pelo job /etc/init/start-ttys.conf. O valor padrão é ACTIVE_CONSOLES=/dev/tty[1-6], que inicia um processo getty para os terminais entre o tty1 e o tty6.

Usar o initctl permite visualizar, iniciar e parar serviços da mesma maneira que o service faz. 
A sintaxe é:

$ initctl opção comando

onde opção pode ser um dos valores:

   start: Inicia um serviço
   stop: para um seriço
   restart: Reinicia um serviço
   reload: Envia um sinal HUP para o serviço. Faz algo como recarregar o arquivo de configuração.
   status: Consulta o estado de um serviço
   list: lista serviços conhecidos
   emit: Emite um evento


Um bom resumo de como usar o initctl e muitos outros recursos do upstart podem ser encontrados em http://upstart.ubuntu.com/cookbook .




Systemd

 


Ao invés de scripts bash, o systemd usa arquivos .service . Adicionalmente, o systemd organiza os daemons nos seus próprios Linux cgroups (control groups).

O systemd que é um gerenciador de sistema e sessões para o Linux está rapidamente criando raízes em todas as principais distribuições.

O systemd é compatível com SysVinit e o conceito de níveis de execução é suportado através de targets. O   programa telinit é emulado para trabalhar com níveis de execução.

 As características do systemd como gestor do sistema e de sessões incluem:



  •     É compatível com os scripts sysvinit.
  •     Inicia mais rápido do que os sistemas anteriores.
  •     Fornece recursos de paralelização agressivos.
  •     Usa socket e D-Bus para iniciar serviços.
  •     Substitui shell scripts por programas.
  •     Oferece carregar daemons por demanda.
  •     Mantém o controle de processos utilizando cgroups.
  •     Apoia a criação e restauração de snapshots do estado do sistema.
  •     Mantém pontos montagem e substitui o automount.
  •     Implementa uma lógica de controle de serviço baseado em dependências.
  •     Pode funcionar como um substituto para o SysVinit.
   

Embora o systemd prefira usar um conjunto de novos arquivos de configuração, ele também pode usar arquivos de configuração legado para manter compatibilidade.

Um exemplo de um novo arquivo de configuração seria /etc/hostname, que substitui /etc/sysconfig/network em sistemas Red Hat, /etc/HOSTNAME no SUSE.

Outros arquivos podem incluir:

    /etc/vconsole.conf: mapeamento de teclado padrão e fonte do console.

    /etc/sysctl.d/*.conf: diretório para os parâmetros sysctl do kernel.

    /etc/os-release : arquivo de identificação de distribuição.
   
   
   
    Systemctl
   
systemctl é a principal ferramenta para gerenciar serviços. Sua sintaxe básica é:


$ systemctl [opções] commando [nome]


Abaixo alguns exemplos sobre como usar o systemctl:


    Para mostrar o estado de tudo que o systemd controla:
    $ systemctl


    Para mostra todos os serviços disponíveis:
    $ systemctl list-units -t service --all


    Para mostra apenas os serviços ativos:
    $ systemctl list-units -t service


    Para iniciar (ativar) uma ou mais units:
    $ sudo systemctl start foo
    $ sudo systemctl start foo.service
    $ sudo systemctl start /path/to/foo.service

    em que a unit pode ser um serviço ou um socket.


    Para parar (desativar): 
    $ sudo systemctl stop foo.service


    Para habilitar/desabilitar um serviço:

    $ sudo systemctl enable sshd.service
  $ sudo systemctl disable sshd.service


Isso é o equivalente ao comando chkconfig --add/--del e na verdade não inicia o serviço.


Nota: Alguns comandos do systemctl podem ser executados por usuários não privilegiados, outros precisam de direitos de administrador, o que pode ser alcançado com o uso do sudo.





Para um resumo excelente de como migrar os hábitos do SysVinit para o systemd, veja a página SysVinit to Systemd Cheatsheet disponível no endereço https://fedoraproject.org/wiki/SysVinit_to_Systemd_Cheatsheet.


Mais vistos no mês:

As melhores distribuições Linux para 2017

TuxMath - Tux, do Comando da Matemática. Ensino e diversão a crianças.

Teste de Performance de Rede com Iperf

DHCP - Guia Completo

OPNsense - Firewall Open Source

Aula #14 - Os sistemas de arquivos ext2/ext3/ext4

Ophcrack: Descubra todas as senhas do Windows

SSD no linux

Oracle Linux 7.0 Server com Xfce - Instalação e configurações iniciais