Linux - Guia prático para administradores de sistemas/Inicialização do sistema
Objetivo
editarO 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
editarO 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
editarO 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
editarO 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
editarA 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
editarApó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
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)
editar0 - 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
editarO 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
editarExemplo 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
editarPara 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 -lMakefile 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