Linux - Guia prático para administradores de sistemas/Inicialização do sistema

Origem: Wikilivros, livros abertos por um mundo aberto.

Objetivo[editar | editar código-fonte]

O propósito deste capítulo é explicar como um servidor utilizando o GNU/Linux é inicializado desde a etapa de inicialização do hardware, até o momento que o processo init é inicializado, os scripts de inicialização são executados e o servidor esteja completamente operacional, o processo getty iniciado à espera de logins.

Inicializando o Sistema[editar | editar código-fonte]

O processo de inicialização de sistemas, independentemente do sistema operacional, depende em muito do tipo de hardware em uso. Em dispositivos baseados na arquitetura x86 (intel) quando o computador é inicializado ou reinicializado o processador (CPU) executa uma operação em uma área ( endereço ) conhecido na memória não volátil (flash RAM).


No caso de PCs (Personal Computers) baseados na arquitetura x86, o processo de inicialização (boot) se inicia na BIOS, no endereço 0xFFFF0. O primeiro passo da BIOS é executar o Power On Self Test (POST) que tem como principal função a verificação do hardware e a enumeração e inicialização dos dispositivos locais.


Para inicializar o sistema operacional, a BIOS irá então procurar por dispositivos ativos e válidos que estejam listados (em ordem de preferência) na CMOS (boot device). Os dispositivos de boot podem ser floppy disks, hard disks, flash drivers, dispositivos de rede, etc.


De maneira geral, o Linux é inicializado a partir de um disco rígido, onde a MBR ( Master Boot Record ) contém o boot loader, mas não o kernel. A MBR é apenas um setor de 512 bytes, localizado no cilindro 0, setor 1 do seu disco rígido, e portanto não teria condições de abrigar um kernel Linux, mesmo que comprimido. Portanto na MBR apenas reside o suficiente para carregar o primeiro estágio do boot loader.

Boot Loader - Estágio 1[editar | editar código-fonte]

O primeiro estágio do boot loader, ou primary boot loader, localizado nos setores restantes do primeiro cilindro. A única função do primary boot loader é encontrar o secondary boot loader, ou o segundo estágio do boot loader, e carregá-lo na memória. O objetivo do primeiro estágio é usar um programa pequeno que lê em um unico sistema de arquivos.
No GRUB esse estágio é conhecido como 1.5 o e o estágio 1 é o código que é escrito no MBR .

Boot Loader - Estágio 2[editar | editar código-fonte]

O segundo estágio de boot tem como função carregar o kernel do Linux na memória, e opcionalmente um arquivo que simula a memoria RAM (RAM image file).


Os 2 estágios do boot loader combinados formam o LILO ( Linux Loader ) ou o GRUB ( GRand Unified Bootloader ). Iremos nos focar no GRUB, devido ao fato deste ser um gerenciador de boot mais novo, e que corrigiu algumas das falhas do LILO.


No estágio 2 é possível listar e escolher entre diversos tipos de kernel instalados (definidos em /boot/grub/menu.lst), e inclusive passar parâmetros de boot durante a inicialização do sistema.


Quando o segundo estágio estiver carregado na memória o sistema de arquivos é consultado, a imagem do kernel e a imagem initrd são carregados na memória, e quando esse processo é concluído, o boot loader invoca o kernel.

Carregando o Kernel[editar | editar código-fonte]

A imagem do kernel não é propriamente um executável, porém contém uma série de rotinas que permitem que o kernel que se encontra comprimido (zlib) seja expandido, e carregado na memória.


Não pretendemos aqui esmiuçar todas as etapas desse processo, no entanto é importante notar que durante a carga do kernel, a ram image que foi carregada durante o estágio 2 do boot loader é montado temporariamente como root file system, contendo todos os drivers necessários para que o kernel tenha acesso aos diversos dispositivos que ele precise.


Esse mecanismo permite que tenhamos imagens de kernel pequenas, e device drivers compilados como módulos e carregados, quando necessários, através de um arquivo que pode ser montado como um sistema de arquivos existente apenas na memória. Tal artifício permite que o kernel seja completamente carregado sem que um disco físico seja de fato acessado. Em uma etapa futura da carga do kernel, esse sistema de arquivos temporários será substituído pelo root file system padrão.


Esse mecanismo garante uma grande flexibilidade a sistemas Linux uma vez que permite inclusive que o próprio root file system resida em um servidor remoto (NFS).

Threads do Kernel[editar | editar código-fonte]

Após a inicialização básica, o kernel cria também vários processos no espaço de usuário. Estes aparecem na listagem de diretórios entre colchetes, a exemplo do [kswapd], [kjournald], etc. Destes processos que aparecem no inicio da listagem de processos, normalmente com números identificadores baixos, 1 (init), 2, 3..., apenas o init é um processo de usuário completo, os demais são na verdade partes do kernel que por razões de escalonamento foram organizados para se parecer com processos. Assim que as threads do kernel são criadas, o papel destes na inicialização termina, e o processo de ativação de todos os outros serviços fica a cargo do init através de scripts de inicialização.


A nomenclatura do processo na coluna CMD corresponde a [NomeDoProcesso/Numero], onde Numero significa o processador em que o processo está alocado.


linux:/etc/init.d # ps -ef
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0  2008 ?        00:00:59 init [3]
root         2     1  0  2008 ?        00:00:00 [migration/0]
root         3     1  0  2008 ?        00:01:13 [ksoftirqd/0]
root         8     1  0  2008 ?        00:07:45 [events/0]
root        11     1  0  2008 ?        00:00:00 [khelper]
root        12     1  0  2008 ?        00:00:00 [kthread]
root        22    12  0  2008 ?        00:00:06 [kblockd/0]
root        63    12  0  2008 ?        00:00:00 [cio_chp]
root        64    12  0  2008 ?        00:00:00 [cio]
root        65    12  0  2008 ?        00:00:00 [cio_notify]
root        66    12  0  2008 ?        00:00:00 [kslowcrw]
root       117    12  0  2008 ?        00:00:00 [appldata]
root       131    12  0  2008 ?        00:01:30 [pdflush]
root       132    12  0  2008 ?        00:00:12 [pdflush]
root       133     1  0  2008 ?        00:01:16 [kswapd0]
root       134    12  0  2008 ?        00:00:00 [aio/0]
root       140    12  0  2008 ?        00:00:00 [cqueue/0]
root       160     1  0  2008 ?        00:00:00 [kmcheck]
root       388     1  0  2008 ?        00:00:17 [kjournald]
root       437     1  0  2008 ?        00:00:03 /sbin/udevd --daemon
root       707     1  0  2008 ?        00:00:00 /usr/sbin/vsftpd
root      1405     1  0  2008 ?        00:00:00 [kjournald]
root      1407     1  0  2008 ?        00:00:01 [kjournald]
root      1409     1  0  2008 ?        00:00:05 [kjournald]
root      1411     1  0  2008 ?        00:03:24 [kjournald]
root      1413     1  0  2008 ?        00:00:02 [kjournald]
root      1415     1  0  2008 ?        00:00:00 [kjournald]
root      1417     1  0  2008 ?        00:00:00 [kjournald]
...


O Processo INIT
[editar | editar código-fonte]

Após a carga e inicialização, o kernel inicia o primeiro programa em user space. Até esse momento, nenhuma outra aplicação baseada em blibliotecas padrão C é executada.


De modo geral, em desktops e servidores linux padrão, após a carga do kernel, o programa /sbin/init é executado, porém isso não é obrigatório. Dispositivos embarcados, por exemplo, não requerem uma inicialização extensiva através do init. É possível por exemplo, após a inicialização do kernel, iniciar um utilitário shell e a partir deste iniciar os processos necessários.


O arquivo de configuração que determina o funcionamento do processo init é o /etc/inittab, entretando pelo fato desse arquivo não ter uma sintaxe fácil de compreender, as distribuições Linux atuais utilizam-se deste para, a partir de um processo (/etc/init.d/rc), determinar o conjunto de scripts que deverão ser executados, dependendo do runlevel escolhido.


Por padrão esses scripts são armazenados sob a estrutura de diretórios /etc/rc.d/rc[0-6,S].d/ e são na verdade scripts simples, baseados em sh (base na verdade) com a função de além de realizar configurações simples durante o processo de boot (hostname, endereço ip, rotas, etc) também são responsáveis por iniciar, parar e reiniciar os daemons que devem ficar em execução no servidor.


No decorrer do processo init, o programa getty é invocado e executado a partir do arquivo de configuração /etc/inittab com a finalidade de abrir conexões ttys (sejam dispositivos reais ou virtuais localizados em /dev) como por exemplo: consoles virtuais, portas seriais, portas do modem, dentre outros, e iniciar a autenticação do usuário chamando o processo login, o qual fica no estado de espera, aguardando o nome do usuário e senha. Caso as informações estejem corretas, uma conexão tty será liberada para o usuário autenticado.

Níveis de Execução (runlevel)[editar | editar código-fonte]

0 - Nível em que o sistema está completamente desligado

1 ou S - representa o modo de monousuário

2 - Primeiro modo multiusuário (sem rede)

3 - Modo multiusuário

4 - Não Usado ( "definível" )

5 - Modo multiusuário (X11)

6 - Reboot (Nível onde o sistema ficará reinicializando)

GRUB : O GRand Unified Boot Loader[editar | editar código-fonte]

O GRUB é o gerenciador de boot mais popular nos dias atuais, e também o padrão das maiores distribuições Linux existentes ( Suse, RedHat, Fedora ). A vantagem mais perceptível do GRUB é que ele transformou o processo usual de 2 estágios em um processo de 3 estágios (1, 1.5 e 2), onde no estágio intermediário ( 1.5 ) o boot loader toma conhecimento do sistema de arquivos onde o kernel reside e não mais acesso a um setor "raw" do disco rígido. Não requer, como o LILO, que o setor de boot seja atualizado a cada modificação no arquivo de configuração. Após o GRUB ser instalado no setor de boot (MBR) com o  comando grub-install o seu arquivo de configuração será lido a cada inicialização, o que garante uma maior flexibilidade a esse gerenciador de boot.


O GRUB não faz distinção entre discos IDE e SCSI, ou seja, existe uma referência na ordem de como os discos são reconhecidos na BIOS influenciando na nomenclatura dos dispositivos válidos no GRUB, por exemplo, se um servidor tiver 02 discos rígidos IDE, 01 SCSI e 01 floppy disk, o GRUB identificará da seguinte forma:

--> Primeiro disco: IDE ( hd0 )

--> Segundo disco: IDE ( hd1)

--> Terceiro disco: SCSI ( hd2 ) 

--> Floppy Disk: ( fd0 )

Nesse exemplo, caso o segundo disco tenha 02 partições, a representação pelo GRUB será: (hd1,0) e (hd1,1).

Como instalar o GRUB no disco master da controladora IDE primária?

grub-install '(hd0,0)'


Exemplo de um arquivo de configuração GRUB (/boot/grub/grub.conf)

default=0
timeout=10
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
title OpenSuse 11.0
     root (hd0,0)
     kernel /boot/vmlinuz-2.6.9-5 ro root=/dev/hda1
title WindowsXP
     rootnoverify (hd0,0)
     chainloader +1

Scripts de Inicialização [editar | editar código-fonte]

Exemplo do script de inicialização do sshd:


Observação: O campo # Default-Start, no exemplo abaixo, significa que os valores padrões para a inicialização do serviço de sshd pelo script de inicialização, serão os níveis de execução 3 e 5. No campo # Default-Stop, informa que esse serviço estará parado quando os níveis de execução forem 0, 1, 2 e 6.

#! /bin/sh
# Copyright (c) 1995-2000 SuSE GmbH Nurenberg, Germany.
#
# Author: Jiri Smid <feedback@suse.de>
#
# /etc/init.d/sshd
#
#   and symbolic its link
#
# /usr/sbin/rcsshd
#
### BEGIN INIT INFO
# Provides: sshd
# Required-Start: $network $remote_fs
# Required-Stop: $network $remote_fs
# Default-Start: 3 5
# Default-Stop: 0 1 2 6
# Description: Start the sshd daemon
### END INIT INFO

SSHD_BIN=/usr/sbin/sshd
test -x $SSHD_BIN || exit 5

SSHD_SYSCONFIG=/etc/sysconfig/ssh
test -r $SSHD_SYSCONFIG || exit 6
. $SSHD_SYSCONFIG

SSHD_PIDFILE=/var/run/sshd.init.pid

. /etc/rc.status

# Shell functions sourced from /etc/rc.status:
#      rc_check         check and set local and overall rc status
#      rc_status        check and set local and overall rc status
#      rc_status -v     ditto but be verbose in local rc status
#      rc_status -v -r  ditto and clear the local rc status
#      rc_failed        set local and overall rc status to failed
#      rc_reset         clear local rc status (overall remains)
#      rc_exit          exit appropriate to overall rc status

# First reset status of this service
rc_reset

case "$1" in
    start)
        if ! test -f /etc/ssh/ssh_host_key ; then
            echo Generating /etc/ssh/ssh_host_key.
            ssh-keygen -t rsa1 -b 1024 -f /etc/ssh/ssh_host_key -N ''
        fi
        if ! test -f /etc/ssh/ssh_host_dsa_key ; then
            echo Generating /etc/ssh/ssh_host_dsa_key.

            ssh-keygen -t dsa -b 1024 -f /etc/ssh/ssh_host_dsa_key -N ''
        fi
        if ! test -f /etc/ssh/ssh_host_rsa_key ; then
            echo Generating /etc/ssh/ssh_host_rsa_key.

            ssh-keygen -t rsa -b 1024 -f /etc/ssh/ssh_host_rsa_key -N ''
        fi
        echo -n "Starting SSH daemon"
        ## Start daemon with startproc(8). If this fails
        ## the echo return value is set appropriate.

        startproc -f -p $SSHD_PIDFILE /usr/sbin/sshd $SSHD_OPTS -o "PidFile=$SSHD_PIDFILE"

        # Remember status and be verbose
        rc_status -v
        ;;
    stop)
        echo -n "Shutting down SSH daemon"
        ## Stop daemon with killproc(8) and if this fails
        ## set echo the echo return value.

        killproc -p $SSHD_PIDFILE -TERM /usr/sbin/sshd

        # Remember status and be verbose
        rc_status -v
        ;;
    try-restart)
        ## Stop the service and if this succeeds (i.e. the
        ## service was running before), start it again.
        $0 status >/dev/null &&  $0 restart

        # Remember status and be quiet
        rc_status
        ;;
    restart)
        ## Stop the service and regardless of whether it was
        ## running or not, start it again.
        $0 stop
        $0 start

        # Remember status and be quiet
        rc_status
        ;;
    force-reload|reload)
        ## Signal the daemon to reload its config. Most daemons
        ## do this on signal 1 (SIGHUP).

        echo -n "Reload service sshd"

        killproc -p $SSHD_PIDFILE -HUP /usr/sbin/sshd

        rc_status -v

        ;;
    status)
        echo -n "Checking for service sshd "
        ## Check status with checkproc(8), if process is running
        ## checkproc will return with exit status 0.

        # Status has a slightly different for the status command:
        # 0 - service running
        # 1 - service dead, but /var/run/  pid  file exists
        # 2 - service dead, but /var/lock/ lock file exists
        # 3 - service not running

        checkproc -p $SSHD_PIDFILE /usr/sbin/sshd

        rc_status -v
        ;;
    probe)
        ## Optional: Probe for the necessity of a reload,
        ## give out the argument which is required for a reload.

        test /etc/ssh/sshd_config -nt $SSHD_PIDFILE && echo reload
        ;;
    *)
        echo "Usage: $0 {start|stop|status|try-restart|restart|force-reload|reload|probe}"
        exit 1
        ;;
esac
rc_exit

Ativando , desativando e listando scripts de inicialização[editar | editar código-fonte]

Para listar os scripts passíveis de utilização, ativos ou não basta usar o seguinte comando:

linux:/etc/init.d # chkconfig --help
usage:
        chkconfig -t|--terse [names]            (shows the links)
        chkconfig -e|--edit  [names]            (configure services)
        chkconfig -s|--set   [name state]...    (configure services)
        chkconfig -l|--list [--deps] [names]    (shows the links)
        chkconfig -c|--check name [state]       (check state)
        chkconfig -a|--add   [names]            (runs insserv)
        chkconfig -d|--del   [names]            (runs insserv -r)
        chkconfig -h|--help                     (print usage)
        chkconfig -f|--force ...                (call insserv with -f)

        chkconfig [name]           same as chkconfig -t
        chkconfig name state...    same as chkconfig -s name state
linux:/etc/init.d # chkconfig -l

Makefile 0:off 1:off 2:off 3:off 4:off 5:off 6:off SuSEfirewall2_init 0:off 1:off 2:off 3:off 4:off 5:off 6:off SuSEfirewall2_setup 0:off 1:off 2:off 3:off 4:off 5:off 6:off aaeventd 0:off 1:off 2:off 3:off 4:off 5:off 6:off acct 0:off 1:off 2:off 3:off 4:off 5:off 6:off alsasound 0:off 1:off 2:on 3:on 4:off 5:on 6:off apache2 0:off 1:off 2:off 3:off 4:off 5:off 6:off appldata 0:off 1:off 2:off 3:on 4:off 5:on 6:off atd 0:off 1:off 2:off 3:off 4:off 5:off 6:off auditd 0:off 1:off 2:off 3:on 4:off 5:on 6:off autofs 0:off 1:off 2:off 3:on 4:off 5:on 6:off autoyast 0:off 1:off 2:off 3:off 4:off 5:off 6:off cmm 0:off 1:off 2:off 3:off 4:off 5:off 6:off cpuplugd 0:off 1:off 2:off 3:off 4:off 5:off 6:off cron 0:off 1:off 2:on 3:on 4:off 5:on 6:off cryptcheck 0:off 1:off 2:off 3:off 4:off 5:off 6:off dbus 0:off 1:off 2:off 3:on 4:off 5:on 6:off dumpconf 0:off 1:off 2:off 3:off 4:off 5:off 6:off earlysyslog 0:off 1:off 2:off 3:off 4:off 5:on 6:off evms 0:off 1:off 2:off 3:off 4:off 5:off 6:off gpm 0:off 1:off 2:off 3:off 4:off 5:off 6:off gssd 0:off 1:off 2:off 3:off 4:off 5:off 6:off haldaemon 0:off 1:off 2:off 3:on 4:off 5:on 6:off hsnc 0:off 1:off 2:off 3:off 4:off 5:off 6:off idmapd 0:off 1:off 2:off 3:off 4:off 5:off 6:off joystick 0:off 1:off 2:off 3:off 4:off 5:off 6:off kadmind 0:off 1:off 2:off 3:off 4:off 5:off 6:off kpropd 0:off 1:off 2:off 3:off 4:off 5:off 6:off krb524d 0:off 1:off 2:off 3:off 4:off 5:off 6:off krb5kdc 0:off 1:off 2:off 3:off 4:off 5:off 6:off ldap 0:off 1:off 2:off 3:on 4:off 5:on 6:off lirc 0:off 1:off 2:off 3:off 4:off 5:off 6:off lm_sensors 0:off 1:off 2:off 3:off 4:off 5:off 6:off mdadmd 0:off 1:off 2:off 3:off 4:off 5:off 6:off mon_fsstatd 0:off 1:off 2:off 3:off 4:off 5:off 6:off mon_statd 0:off 1:off 2:off 3:off 4:off 5:off 6:off multipathd 0:off 1:off 2:off 3:off 4:off 5:off 6:off mysql 0:off 1:off 2:off 3:off 4:off 5:off 6:off named 0:off 1:off 2:off 3:off 4:off 5:off 6:off netdump-server 0:off 1:off 2:off 3:off 4:off 5:off 6:off network 0:off 1:off 2:on 3:on 4:off 5:on 6:off nfs 0:off 1:off 2:off 3:on 4:off 5:on 6:off nfsboot 0:off 1:off 2:off 3:on 4:off 5:on 6:off nfsserver 0:off 1:off 2:off 3:off 4:off 5:off 6:off nmb 0:off 1:off 2:off 3:off 4:off 5:off 6:off novell-zmd 0:off 1:off 2:off 3:off 4:off 5:off 6:off nscd 0:off 1:off 2:off 3:on 4:off 5:on 6:off ntp 0:off 1:off 2:off 3:off 4:off 5:off 6:off openct 0:off 1:off 2:off 3:off 4:off 5:off 6:off pcscd 0:off 1:off 2:off 3:off 4:off 5:off 6:off pkcsslotd 0:off 1:off 2:off 3:off 4:off 5:off 6:off portmap 0:off 1:off 2:off 3:on 4:off 5:on 6:off random 0:off 1:off 2:on 3:on 4:off 5:on 6:off raw 0:off 1:off 2:off 3:off 4:off 5:off 6:off resmgr 0:off 1:off 2:on 3:on 4:off 5:on 6:off rpasswdd 0:off 1:off 2:off 3:off 4:off 5:off 6:off rpmconfigcheck 0:off 1:off 2:off 3:off 4:off 5:off 6:off rsyncd 0:off 1:off 2:off 3:off 4:off 5:off 6:off running-kernel 0:off 1:off 2:on 3:on 4:off 5:on 6:off rxstack 0:off 1:off 2:off 3:off 4:off 5:off 6:off saslauthd 0:off 1:off 2:off 3:off 4:off 5:off 6:off sendmail 0:off 1:off 2:off 3:on 4:off 5:on 6:off sharedvol_mount 0:off 1:off 2:off 3:off 4:off 5:off 6:off skeleton.compat 0:off 1:off 2:off 3:off 4:off 5:off 6:off slpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off slurpd 0:off 1:off 2:off 3:on 4:off 5:on 6:off smb 0:off 1:off 2:off 3:off 4:off 5:off 6:off smbfs 0:off 1:off 2:off 3:on 4:off 5:on 6:off snmpd 0:off 1:off 2:on 3:on 4:off 5:on 6:off squid 0:off 1:off 2:off 3:off 4:off 5:off 6:off sshd 0:off 1:off 2:off 3:on 4:off 5:on 6:off suseRegister 0:off 1:off 2:off 3:on 4:off 5:on 6:off svcgssd 0:off 1:off 2:off 3:off 4:off 5:off 6:off synctime 0:off 1:off 2:off 3:on 4:off 5:on 6:off syslog 0:off 1:off 2:on 3:on 4:off 5:on 6:off sysstat 0:off 1:off 2:off 3:off 4:off 5:off 6:off tsm 0:off 1:off 2:off 3:off 4:off 5:off 6:off updateconfig 0:off 1:off 2:off 3:off 4:off 5:off 6:off vmlogrdr 0:off 1:off 2:off 3:off 4:off 5:off 6:off vsftpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off xdm 0:off 1:off 2:off 3:off 4:off 5:on 6:off xfs 0:off 1:off 2:off 3:off 4:off 5:off 6:off xinetd 0:off 1:off 2:off 3:on 4:off 5:on 6:off xpram 0:off 1:off 2:off 3:off 4:off 5:off 6:off z90crypt 0:off 1:off 2:off 3:off 4:off 5:off 6:off xinetd based services:

       chargen:            off
       chargen-udp:        off
       daytime:            off
       daytime-udp:        off
       echo:               off
       echo-udp:           off
       klogin:             off
       kshell:             off
       ktelnet:            off
       netstat:            off
       rexec:              off
       rlogin:             off
       rsh:                on
       rsync:              off
       servers:            off
       services:           off
       swat:               off
       systat:             off
       telnet:             on
       time:               off
       time-udp:           off
       vnc:                off
       vsftpd:             off

Ativando e desativando o serviço sendmail:

linux:/etc/init.d # chkconfig sendmail 3
linux:/etc/init.d # chkconfig sendmail -l
sendmail                  0:off  1:off  2:off  3:on   4:off  5:off  6:off
domsles10:/etc/init.d # chkconfig sendmail off
linux:/etc/init.d # chkconfig sendmail -l
sendmail                  0:off  1:off  2:off  3:off  4:off  5:off  6:off
linux:/etc/init.d # chkconfig sendmail 35
linux:/etc/init.d # chkconfig sendmail -l
sendmail                  0:off  1:off  2:off  3:on   4:off  5:on   6:off