9.1. Engegada del sistema
Quan s'inicia l'ordinador, els molts missatges que apareixen a la consola mostren moltes inicialitzacions i configuracions automàtiques que s'estan executant. A vegades es pot voler alterar lleugerament com funciona aquesta etapa, cosa que significa que cal entendre-la bé. Aquest és el propòsit d'aquesta secció.
En els sistemes amb una BIOS, primer la BIOS pren el control de l'ordinador, inicialitza els controladors i el maquinari, detecta els discos i ho connecta tot. Després, cerca el Master Boot Record (MBR) del primer disc segons l'ordre d'arrencada i carrega el codi emmagatzemat allà (primera etapa). Aquest codi llança la segona etapa i finalment executa el carregador d'arrencada.
A diferència de la BIOS, l'UEFI és més sofisticada, coneix sistemes de fitxers i pot llegir les taules de particions. La interfície cerca en l'emmagatzematge del sistema una partició etiquetada amb un identificador únic global específic (
GUID) que la marqui com la «
EFI System Partition» (
ESP), on es troben els carregadors d'arrencada, gestors d'arrencada, la shell UEFI, etc., i llança el carregador d'arrencada desitjat. Si el «Secure Boot» està activat, el procés d'arrencada verificarà l'autenticitat dels binaris EFI per la signatura (així doncs, en aquest cas es requereix
grub-efi-arquitectura-signed). L'especificació UEFI també defineix el suport per a l'arrencada en mode BIOS antic. Això s'anomena el «
Compatibility Support Module» (
CSM). Si el CSM està habilitat, s'intentarà arrencar des de l'MBR d'una unitat. No obstant això, molts sistemes nous ja no admeten el mode CSM.
En ambdós casos llavors el gestor d'arrencada que toca pren el control i localitza un segon carregador d'arrencada o el nucli en un disc, el carrega i l'executa. El nucli llavors s'inicialitza, i comença a cercar i muntar la partició que conté el sistema de fitxers arrel, i finalment executa el primer programa — init
. Freqüentment, aquesta “partició arrel” i aquest init
es troben, de fet, en un sistema de fitxers virtual que només existeix a la RAM (d'aquí el seu nom, “initramfs”, anteriorment anomenat “initrd” per “disc RAM d'inicialització”). Aquest sistema de fitxers és carregat en memòria pel carregador d'arrencada, sovint des d'un fitxer en un disc dur o des de la xarxa. Conté el mínim necessari perquè el nucli carregui el sistema de fitxers arrel “veritable”: això poden ser mòduls de controladors per al disc dur, o altres dispositius sense els quals el sistema no pot arrencar, o, més freqüentment, scripts d'inicialització i mòduls per a muntar tires de RAID, obrir particions encriptades, activar volums LVM, etc. Un cop la partició arrel està muntada, els “initramfs” passen el control a l'“init” real, i la màquina torna al procés d'arrencada estàndard.
9.1.1. El sistema d'inici de systemd
Aquest “init real” és proveït actualment per systemd i aquesta secció documenta aquest sistema d'inici.
Systemd executa diversos processos, que es fan càrrec de la configuració del sistema: teclat, controladors, sistemes de fitxers, xarxa, serveis. Ho fa mantenint una visió global del sistema en el seu conjunt i dels requisits dels components. Cada component és descrit per un “arxiu d'unitat” o «unit file» (i de vegades més d'un); la sintaxi general es deriva de la sintaxi àmpliament usada dels fitxers “*.ini”, amb parells clau =valor
agrupats entre capçaleres[secció]
. Els arxius d'unitats s'emmagatzemen sota /lib/systemd/system/
i /etc/systemd/system/
; hi ha diferents variants, però aquí ens centrarem en els de “serveis” i “objectius” (o «targets»).
Un “fitxer .service
” de systemd descriu un procés gestionat per systemd. Conté bàsicament la mateixa informació que els antics scripts “init”, però expressada de forma declaratòria (i molt més concisa). Systemd gestiona la major part de les tasques repetitives (començar i aturar el procés, comprovar el seu estat, registrar, abandonar els privilegis, etc.), i el fitxer de servei només necessita omplir els detalls específics del procés. Per exemple, aquí està el fitxer de servei per a SSH:
[Unit]
Description=OpenBSD Secure Shell server
Documentation=man:sshd(8) man:sshd_config(5)
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStartPre=/usr/sbin/sshd -t
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/usr/sbin/sshd -t
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartPreventExitStatus=255
Type=notify
RuntimeDirectory=sshd
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
Alias=sshd.service
La secció [Unit]
conté informació genèrica sobre el servei, com la seva descripció i recursos de pàgines de manual, així com relacions (de dependència i d'ordre) amb altres serveis. La part [Service]
conté les declaracions relacionades amb l'execució del servei (inici, aturada, matar, reinici), els directoris i els fitxers de configuració utilitzats. L'última secció, [Install]
, també porta informació sobre en quins «targets» s'ha d'instal·lar el servei i, en aquest cas, l'àlies que es pot utilitzar en lloc del nom del servei. Com podeu veure, hi ha molt poc codi aquí, només declaracions. Systemd té cura de mostrar informes de progrés, fer un seguiment dels processos, i fins i tot reiniciar-los quan sigui necessari. La sintaxi d'aquests fitxers es descriu completament en diverses pàgines de manual (per exemple systemd.service(5), systemd.unit(5), systemd.exec(5), etc.).
Un “fitxer .target
” de systemd descriu un estat del sistema on se sap que un conjunt de serveis estan operatius. Es pot considerar com un equivalent del antics nivells d'execució. Un dels objectius és local-fs.target
; quan s'hi arriba, la resta del sistema pot assumir que tots els sistemes de fitxers locals estan muntats i són accessibles. Altres objectius són network-online.target
i sound.target
(per la llista completa d'objectius especials veieu systemd.special(7)). Les dependències d'un objectiu es poden llistar dins del fitxer objectiu (a la línia Requires=
), o utilitzant un enllaç simbòlic a un fitxer de servei al directori /lib/systemd/system/objectiu.target.wants/
. Per exemple, /etc/systemd/system/printer.target.wants/
conté un enllaç a /lib/systemd/system/cups.service
; systemd assegurarà que CUPS s'està executant per assolir printer.target
.
Com que els arxius d'unitats són declaratius en lloc de scripts o programes, no es poden executar directament, i només s'interpreten per systemd; diverses utilitats permeten a l'administrador interaccionar amb systemd i controlar l'estat del sistema i de cada component.
La primera utilitat d'aquest tipus és systemctl
. Quan s'executa sense cap argument, llista tots els fitxers d'unitat coneguts per systemd (excepte els que han estat anul·lats), així com el seu estat. systemctl status
ofereix una millor visió dels serveis, així com els processos relacionats. Si se li dona el nom d'un servei (com amb systemctl status ntp.service
), retorna encara més detalls, així com les últimes línies de registre relacionades amb el servei (com es detallarà més endavant).
Engegar un servei manualment és simplement qüestió d'executar systemctl start nom-del-servei.service
. Com es pot deduir, per aturar el servei es fa amb systemctl stop nom-del-servei.service
; altres subordres inclouen reload
i restart
.
Per controlar si un servei està activat (és a dir, si s'iniciarà automàticament en arrencar), utilitzeu systemctl enable nom-del-servei.service
(o disable
). is-enabled
permet comprovar saber si està activat o no.
Una característica interessant de systemd és que inclou un component enregistrador anomenat journald
. És un complement a sistemes de registre més tradicionals com ara syslogd
, però aporta característiques interessants com un enllaç formal entre un servei i els missatges que genera, i la capacitat de capturar missatges d'error generats per la seva seqüència d'inicialització. Els missatges es poden mostrar més endavant, amb una mica d'ajuda de l'ordre journalctl
. Sense cap argument, simplement mostrarà tots els missatges de registre generats des de l'arrencada del sistema; rarament s'utilitzarà d'aquesta manera. La majoria de vegades s'utilitzarà amb un identificador de servei:
#
journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 10:08:49 CEST, end at Tue 2015-03-31 17:06:02 CEST. --
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:08:55 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Received SIGHUP; restarting.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on 0.0.0.0 port 22.
Mar 31 10:09:00 mirtuel sshd[430]: Server listening on :: port 22.
Mar 31 10:09:32 mirtuel sshd[1151]: Accepted password for roland from 192.168.1.129 port 53394 ssh2
Mar 31 10:09:32 mirtuel sshd[1151]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Una altra opció útil de la línia d'ordres és -f
, que indica a journalctl
que continui mostrant els missatges nous a mesura que s'emeten (de manera similar a cat -f fitxer
).
Si un servei no sembla estar funcionant com s'esperava, el primer pas per resoldre el problema és comprovar que el servei s'està executant amb systemctl status
; si no ho està, i informació donada per l'anterior ordre no són suficients per diagnosticar el problema, es pot comprovar els registres recollits per journald sobre aquest servei. Per exemple, assumint que el servidor SSH no funciona:
#
systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
Active: failed (Result: start-limit) since Tue 2015-03-31 17:30:36 CEST; 1s ago
Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
Process: 1188 ExecStart=/usr/sbin/sshd -D $SSHD_OPTS (code=exited, status=255)
Main PID: 1188 (code=exited, status=255)
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
#
journalctl -u ssh.service
-- Logs begin at Tue 2015-03-31 17:29:27 CEST, end at Tue 2015-03-31 17:30:36 CEST. --
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:27 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Received SIGHUP; restarting.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on 0.0.0.0 port 22.
Mar 31 17:29:29 mirtuel sshd[424]: Server listening on :: port 22.
Mar 31 17:30:10 mirtuel sshd[1147]: Accepted password for roland from 192.168.1.129 port 38742 ssh2
Mar 31 17:30:10 mirtuel sshd[1147]: pam_unix(sshd:session): session opened for user roland by (uid=0)
Mar 31 17:30:35 mirtuel sshd[1180]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1182]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:35 mirtuel sshd[1184]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:35 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:35 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1186]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel sshd[1188]: /etc/ssh/sshd_config line 28: unsupported option "yess".
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service: main process exited, code=exited, status=255/n/a
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
Mar 31 17:30:36 mirtuel systemd[1]: ssh.service start request repeated too quickly, refusing to start.
Mar 31 17:30:36 mirtuel systemd[1]: Failed to start OpenBSD Secure Shell server.
Mar 31 17:30:36 mirtuel systemd[1]: Unit ssh.service entered failed state.
#
vi /etc/ssh/sshd_config
#
systemctl start ssh.service
#
systemctl status ssh.service
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled)
Active: active (running) since Tue 2015-03-31 17:31:09 CEST; 2s ago
Process: 1023 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
Main PID: 1222 (sshd)
CGroup: /system.slice/ssh.service
└─1222 /usr/sbin/sshd -D
#
Després de comprovar l'estat del servei («failed»), es passa a comprovar els registres; indiquen un error en el fitxer de configuració. Després d'editar el fitxer de configuració i esmenar l'error, es reinicia el servei, i després es verifica que efectivament s'està executant.
9.1.2. El sistema d'inici de System V
El sistema d'inici del System V (que anomenarem “init” per abreujar) executa diversos processos seguint les instruccions del fitxer /etc/inittab
. El primer programa que s'executa (que correspon amb el pas sysinit) és /etc/init.d/rcS
, un script que executa tots els programes del directori /etc/rcS.d/
.
Entre aquests, trobareu successivament programes encarregats de:
configurar el teclat de la consola;
carregar controladors: la majoria dels mòduls del nucli són carregats per ell mateix a mida que es detecta el maquinari; controladors addicionals són carregats automàticament quan els mòduls corresponents es llisten a /etc/modules
;
verificar la integritat dels sistemes de fitxers;
muntar particions locals;
configurar la xarxa;
muntar sistemes de fitxers en xarxa (NFS).
Després d'aquesta etapa, init
pren el control i inicia els programes habilitats en el nivell d'execució (o «runlevel») per defecte (que normalment és el nivell d'execució 2). Executa /etc/init.d/rc 2
, un script que inicia tots els serveis que estan llistats a /etc/rc2.d/
i els noms dels quals comencen amb la lletra “S”. El número de dues xifres que segueix s'havia utilitzat històricament per definir l'ordre en què els serveis havien d'iniciar-se, però actualment el sistema d'arrencada per defecte utilitza insserv
, que ho planifica tot automàticament basant-se en les dependències dels scripts. Així, cada script d'arrencada declara les condicions que s'han de complir per iniciar o aturar el servei (per exemple, si ha de començar abans o després d'un altre servei); init
després les executa en l'ordre que compleix aquestes condicions. La numeració estàtica dels scripts ja no es té en compte (però sempre han de tenir un nom que comenci amb “S” seguit de dos dígits i el nom real de l'script utilitzat per a les dependències). En general, els serveis bàsics (com ara l'enregistrament amb rsyslog
, o l'assignació de ports amb portmap
) són iniciats primer, seguits pels serveis estàndard i la interfície gràfica (gdm3
).
Aquest sistema d'arrencada basat en dependències fa possible automatitzar la “re-numeració”, que podria ser bastant tediosa si s'hagués de fer manualment, i limita els riscos de l'error humà, ja que la planificació es duu a terme d'acord amb els paràmetres indicats. Un altre avantatge és que els serveis poden ser engegats en paral·lel quan són independents els uns dels altres, la qual cosa pot accelerar el procés d'arrencada.
init
distingeix diversos nivells d'execució, de manera que pot canviar d'un a un altre amb el comandament telinit nou-nivell
. Immediatament, init
executa /etc/init.d/rc
de nou amb el nou nivell d'execució. Aquest script iniciarà els serveis que falten i aturarà els que ja no es volen. Per fer això, es refereix al contingut del /etc/rcX.d
(on X representa el nou nivell d'execució). Els scripts que comencen amb “S” (de l'anglès «Start») són els serveis que s'iniciaran; els que comencen amb “K” (de l'anglès «Kill») són els serveis que s'aturaran. L'script no inicia cap servei que ja estigués actiu en el nivell d'execució anterior.
Per defecte, l'init de System V a Debian utilitza quatre nivells d'execució diferents:
El nivell 0 només s'utilitza temporalment, mentre l'ordinador s'està apagant. Com a tal, només conté scripts “K”.
El nivell 1, també conegut com a mode “mono-usuari”, correspon al sistema en mode degradat; inclou només serveis bàsics, i està destinat a operacions de manteniment on la interaccions amb usuaris ordinaris no són desitjades.
El nivell 2 és el nivell d'operació normal, que inclou serveis de xarxa, una interfície gràfica, inicis de sessió d'usuari, etc.
El nivell 6 és similar al nivell 0, però s'utilitza durant la fase d'aturada que precedeix un reinici.
Hi ha altres nivells, com ara del 3 al 5. Per defecte estan configurats per operar de la mateixa manera que el nivell 2, però l'administrador pot modificar-los (afegint o suprimint scripts als corresponents /etc/rcX.d
) per adaptar-los a necessitats particulars.
Tots els scripts continguts en els diversos directoris /etc/rcX.d
són realment enllaços simbòlics — creats després de la instal·lació dels paquets pel programa update-rc.d
— apuntant als scripts reals que s'emmagatzemen a /etc/init.d/
. L'administrador pot ajustar els serveis disponibles a cada nivell d'execució re-executant update-rc.d
amb paràmetres adaptats. La pàgina del manual update-rc.d(1) descriu la sintaxi detalladament. Tingueu en compte que eliminar tots els enllaços simbòlics (amb el paràmetre remove
) no és un bon mètode per desactivar un servei. En lloc d'això simplement haureu de configurar-lo per no engegar-se al nivell d'execució desitjat (mantenint però les crides corresponents per aturar-lo en cas que el servei s'executi en el nivell d'execució anterior). Atès que update-rc.d
té una interfície una mica complexa, podeu preferir utilitzar rcconf
(del paquet rcconf) que proporciona una interfície més fàcil d'utilitzar.
Finalment, init
inicia programes de control per a diverses consoles virtuals (getty
). Mostra un indicador, esperant un nom d'usuari, i després executa login usuari
per iniciar una sessió.