Når du starter datamaskinen, vises de mange meldinger på konsollskjermen mange automatiske oppsett og igangsettinger. Noen ganger kan du ønske å endre litt på hvordan dette stadiet fungerer, noe som betyr at du må forstå det godt. Det er hensikten med dette avsnittet.
9.1.1. Systemd init system
Den «ekte init-en» blir nå levert av systemd, og dette avsnitter dokumenterer dette init-systemet.
Systemd utfører flere prosesser, som har ansvaret for å sette opp systemet: tastatur, drivere, filsystemer, nettverk, tjenester. Den gjør dette mens du holder et overordnet oppsyn på systemet som en helhet, og kravene til komponentene. Hver komponent er beskrevet av en «enhetsfil» («unit file») (noen ganger mer); den generelle syntaksen er avledet fra det mye brukte «* INI-filer» syntaks, med nøkkel = verdi
par gruppert mellom [seksjon]
topptekster. «Unit filer» er lagret under /lib/systemd/system/
, og /etc/systemd/system/
. De kommer i flere varianter, men her vil vi fokusere på «tjenester» og «mål».
En systemd «tjenestefil» beskriver en prosess styrt av systemd. Den inneholder omtrent den samme informasjonen som i et gammelt stil init-skript, men uttrykt på en deklaratorisk (og mye mer konsis) måte. Systemd håndterer mesteparten av de repeterende oppgavene (som starter og stopper prosessen, sjekker statusen, loggingen, dropper privilegier, og så videre), og tjenestefilen trenger bare å fylle ut detaljene i prosessen. For eksempel, her er tjenestefilen for SSH:
[Unit]
Description=OpenBSD Secure Shell server
After=network.target auditd.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]
EnvironmentFile=-/etc/default/ssh
ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
[Install]
WantedBy=multi-user.target
Alias=sshd.service
Som du kan se, er det svært lite kode her, bare deklarasjoner. Systemd tar seg av visning av fremdriftsrapporter, holder orden på prosessene, og starter dem selv når det trengs.
En systemd «målfil» («target file») beskriver et systems tilstand, hvor et sett av tjenester som er kjent for å være operasjonelle. Det kan sees på som å tilsvare det gammeldagse kjørenivået. Ett av målene er local-fs.target
; Når det er nådd, kan resten av systemet gå ut fra at alle de lokale filsystemer er montert og tilgjengelige. Andre mål inkluderer network-online.target
og sound.target
. Avhengigheter for et mål kan enten være oppført i målfilen (i Requires=
-linjen), eller man kan bruke en symbolsk fil i /lib/systemd/system/targetname.target.wants/
-mappen. For eksempel inneholder /etc/systemd/system/printer.target.wants/
en link til /lib/systemd/system/cups.service
; systemd vil derfor sikre at CUPS kjører, for å nå printer.target
.
Siden enhetsfiler er deklarative heller enn skripter eller programmer, kan de ikke kjøres direkte, og de blir bare tolket av systemd. Flere verktøy tillater derfor administratoren å samhandle med systemd for å kontrollere tilstanden til systemet, og for hver komponent.
Det første slikt verktøy er systemctl
. Kjørt uten argumenter, viser den alle enhetsfiler som er kjent for systemd (bortsett fra de som er blitt deaktivert), samt deres status. systemctl status
gir en bedre oversikt over tjenestene, samt relaterte prosesser. Hvis navnet på en tjeneste er gitt (som i systemctl status ntp.service
), returnerer den enda flere detaljer, så vel som de få siste logglinjer knyttet til denne tjenesten (mer om det senere).
Å starte en tjeneste for hånd er en enkel sak, kjør systemctl start tjenestenavn.service
. Som man kan gjette seg til, å stoppe tjenesten gjøres med systemctl stop tjenestenavn.service
. Andre underkommandoer inkluderer reload
og restart
.
For å kontrollere om en tjeneste er aktiv (dvs. om den vil komme i gang automatisk ved oppstart), bruk systemctl enable tjenestnavn.service
(eller disable
). is-enabled
åpner for å sjekke tjenestens status.
Et interessant trekk ved systemd er at den inneholder en loggingskomponent som heter journald
. Den kommer som et supplement til mer tradisjonelle loggingssystemer, for eksempel syslogd
, men den legger til interessante funksjoner som en formell kobling mellom en tjeneste og meldingene den genererer, og evnen til å fange opp feilmeldinger generert fra sin initialiseringssekvens. Meldingene kan vises senere, med litt hjelp fra journalctl
-kommandoen. Uten noen argumenter, avgir den bare alle loggmeldinger som har oppstått etter oppstart av systemet. Det vil sjelden bli brukt på den måten. Mesteparten av tiden vil den bli brukt med en tjenesteidentifikator:
#
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)
En annen nyttig kommandolinjemarkør er -f
, som instruerer journalctl
til å fortsette å vise nye meldinger etter hvert som de er sendt ut (mye på samme måte som tail -f file
).
Hvis en tjeneste ikke ser ut til å virke som forventet, er første skritt for å løse problemet å kontrollere at tjenesten faktisk kjører, med systemctl status
. Hvis den ikke kjører, og meldingene er gitt av den første kommandoen ikke er nok til å diagnostisere problemet, sjekk loggene samlet av journald om denne tjenesten. For eksempel, anta at SSH-tjeneren ikke virker:
#
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
#
Etter å ha sjekket status på tjenesten (feilet), gikk vi videre til å sjekke loggene. De indikerer en feil i oppsettsfilen. Etter å ha endret på oppsettsfilen og fikset feilen, starter vi tjenesten, og kontroller så at den faktisk kjører.
9.1.2. System V init system
System V init system (som vi kaller init for korthets skyld) utfører flere prosesser, etter anvisning fra
/etc/inittab
-filen. Det første program som kjøres (som tilsvarer
sysinit trinnet) er
/etc/init.d/rcS
, et skript som kjører alle programene i
/etc/rcS.d/
-mappen.
Blant disse finner du suksessivt programmer med ansvar for:
oppsettet av konsollets tastatur;
laste drivere: de fleste av kjernemodulene er lastet av kjernen selv i takt med at maskinvaren blir oppdaget; ekstra drivere blir deretter lastet inn automatisk når de korresponderende modulene er oppført i /etc/modules
;
sjekke integriteten til filsystemene;
montere lokale partisjoner;
sette opp nettverket;
montere nettverk filsystemer (NFS).
Etter dette trinnet tar init
over, og starter programmene aktivert i standard kjørenivå (som vanligvis er driftsnivå 2). Den utfører /etc/init.d/rc 2
, et skript som starter alle tjenestene som er oppført i /etc/rc2.d/
, og der navnet begynner med bokstaven «S». Det tosifrede nummer som følger, har historisk blitt brukt til å definere i hvilken rekkefølge tjenestene måtte startes, men i dag brukes det standard oppstartssystemet insserv
, som berammer alt automatisk basert på skriptenes avhengigheter. Hvert oppstartsskript melder om betingelsene som må være oppfylt for å starte eller stoppe tjenesten (for eksempel hvis det må starte før eller etter en annen tjeneste); så starter init
dem i den rekkefølgen som oppfyller disse betingelsene. Skriptenes statiske nummerering tas derfor ikke lenger i betraktning (men de må alltid ha et navn som begynner med «S» etterfulgt av to sifre, og selve navnet på skriptet som brukes for avhengighetene. Vanligvis startes basistjenester (for eksempel logger med rsyslog
, eller tildeling av port med portmap
) først, fulgt av standardtjenestene og det grafiske brukergrensesnittet (gdm3
).
Dette avhengighetsbaserte oppstartssystemet gjør det mulig å automatisere renummerering, som kan være ganske kjedelig hvis det må gjøres manuelt. Det begrenser risikoen for menneskelige feil, ettersom tidsrekkefølgen blir gjennomført i henhold til de parameterne som er angitt. En annen fordel er at tjenester kan startes parallelt når de er uavhengige av hverandre, noe som kan akselerere oppstartsprosessen.
init
skiller mellom ulike kjørenivåer, så det kan bytte fra ett til et annet med telinit new-level
-kommandoen. Umiddelbart vil init
kjøre /etc/init.d/rc
igjen med det nye kjørenivået. Dette skriptet vil da starte de manglende tjenestene, og stoppe de som ikke lenger er ønsket. For å gjøre dette viser det til innholdet i /etc/rcX.d
(der X representerer det nye kjørenivået). Skript som begynner med «S» (som i «Start») er tjenester som skal i gang; de som starter med «K» (som i «Kill») er de tjenestene som skal stoppes. Skriptet starter ikke noen tjenester som allerede var aktive med det forrige driftsnivået.
Som standard bruker System V init i Debian fire forskjellige driftsnivåer:
Nivå 0 brukes bare midlertidig, mens maskinen slår seg av. Dermed inneholder den bare mange «K»-skripter.
Nivå 1, også kjent som enkeltbrukermodus, tilsvarer systemet i nedgradert modus; det inneholder bare basistjenester, og er beregnet for vedlikeholdsoperasjoner hvor samhandling med vanlige brukere ikke er ønsket.
Nivå 2 er nivået for normal drift, som omfatter nettverkstjenester, et grafisk grensesnitt, brukerpålogging, etc.
Nivå 6 er lik nivå 0, bortsett fra at det brukes under nedkoblingsfasen før en omstart.
Andre nivåer finnes, spesielt 3 til 5. Som standard er de satt opp til å operere på samme måte som nivå 2, men administratoren kan endre dem (ved å legge til eller slette skript i de tilsvarende /etc/rcX.d
kataloger) for å tilpasse dem til spesielle behov.
Alle skriptene som inngår i de ulike /etc/rcX.d
-kataloger er egentlig bare symbolske lenker - opprettet ved pakkeinstallasjon av update-rc.d
-programmet - som peker til selve skriptet som er lagret i/etc/init.d/
. Administratoren kan finjustere tjenestene som er tilgjengelige i hvert kjørenivå ved å kjøre update-rc.d
igjen med justerte parametre. Manualsiden update-rc.d(1) beskriver syntaksen i detalj. Vær oppmerksom på at å fjerne alle symbolske lenker (med remove
-parameteret) ikke er noen god metode for å deaktivere en tjeneste. I stedet bør du bare sette den opp til ikke å starte i det ønskede kjørenivået (mens man skjermer de samsvarende påkallinger for å stoppe den i det tilfelle tjenesten bruker det forrige kjørenivået. Siden update-rc.d
har et noe innfløkt grensesnitt, kan du foretrekke å bruke rcconf
(fra rcconf-pakken som gir et mer brukervennlig grensesnitt.
Til slutt, init
starter kontrollprogrammer for ulike virtuelle konsoller (getty
). Den viser en ledetekst, venter på et brukernavn, og så kjører login bruker
for å starte en økt.