Konfigurační soubory - I
Konfigurace operačního systému Linux systému je řešena pomocí konfiguračních souborů a skriptů. My si ve třech čátech představíme jednotlivé skripty a soubory. Začneme představení konfiguračních souborů a skriptů, které mají na starost inicializaci a bezpečné ukončení běhu systému.
Soubor /etc/inittab
Na konci bootování jádra je spuštěn proces init (/sbin/init), první uživatelský proces, který má za úkol dokončit spouštění systému. Chování procesu init určuje obecně právě obsah souboru /etc/inittab.
Jelikož proces init je v našem případě vlastně jen symbolickým odkazem na spustitelný soubor Busyboxu, musíme obsah souboru /etc/inittab oproti klasickému procesu init přizpůsobit specifiku Busyboxu.
Ve výchozí konfiguraci Busybox existenci souboru /etc/inittab nevyžaduje. My jsme Busybox ovšem nakonfigurovali tak, aby jeho přítomnost v systému Busybox vyžadoval. Díky tomu můžeme ovlivňovat chování systému při jeho spouštění a vypínání.
Obsah souboru:
# /etc/inittab # format <id>:<runlevels>:<action>:<proces> # startup ::sysinit:/etc/init.d/rcS # when restarting init process ::restart:/sbin/init # restart or shutdown system ::ctrlaltdel:/sbin/reboot ::shutdown:/etc/init.d/rcK # virtual terminals with login shell tty1::respawn:-/bin/sh tty2::respawn:-/bin/sh # serial port terminals with login shell ttyS0::respawn:/sbin/getty -L ttyS0 38400 vt100
Něco málo k jeho formátu. Obsah souboru se skládá z několika řádků, které mají daný pevný formát:
- Položka id určuje jednak číslo kontrolního terminálu (proto jí u většiny položek necháváme prázdnou) a pak také určuje na kterých konzolách se má spustit shell, případně login.
- Položka runlevels je Busyboxem ignorována, protože úrovně běhu Busybox nepodporuje.
- Položka action definuje, co má proces init dělat s programem určeným položkou process.
- Položka proces definuje program, který je předmětem dané akce (action).
Vysvětlivky (k obsahu souboru):
- při startu systému (akce sysinit) ještě předtím než proces init otevře systémovou konzoli a umožní přihlášení uživatele, se má provést skript /etc/init.d/rcS.
- při vypínání systému (akce shutdown) se má jako úplně poslední uživatelský program provést úklidový skript spustí skript /etc/init.d/rcK.
- při stisku Ctrl+Alt+Del (akce ctrlatldel) se provede příkaz reboot, který provede reset systému.
- při restartu procesu init (akce restart) se má opět spustit proces init.
- proces init má otevřít dva virtuální teminály, spustit na nich shell daný symbolickým odkazem /bin/sh a vyžadovat příhlášení uživatele. Povinnost se přihlásit je dána pomlčkou před cestou k shellu (bohužel nám to v žádné dostupné verzi Busyboxu dosud nefungovalo). Akce respawn říká, že v případě ukončení běhu shellu má být tento znovu spuštěn.
- krom toho, má proces init také čekat na terminálové spojení na sériovém portu ttyS0 rychlostí 38400 Bd, vyžadovat příhlášení uživatele (volba -L) a očekávat terminálové zařízení typu VT100.
Skript /etc/init.d/rcS
Jak jsme si řekli před chvílí, shellový skript /etc/init.d/rcS má za úkol provést poslední kroky při startu systému ještě předtím, než jsou otevřena terminálová spojení a uživatel může začít se systémem pracovat. Typicky se v něm provádí nastavení síťového adaptéru (IP adresa, atd.), rozběhnutí služeb systému, připojení zbývajících souborových systémů (kromě kořenového - ten je už připojen při bootování jádra), atd.
Obsah souboru:
#!/bin/sh # /etc/init.d/rcS: The first script started by init process # user settings IP=192.168.1.15 NETMASK=255.255.255.0 GATEWAY=192.168.1.254 # user functions check_status() { if [ $? = 0 ] then echo "[done]" else echo "[failed]" fi } mountit() { if ! mountpoint -q $1 then echo -en "Mounting $1...\t\t\t\t" mount $1 &> /dev/null check_status fi } # 1: print an intro echo cat /etc/issue.rcs echo # 2: create /dev on RAM disk to be able to run out of RFS mountit /dev # 3: create mount points on /dev dir created in RAM mkdir -p /dev/pts mkdir -p /dev/shm # 4: mount file systems needed by kernel and processes mountit /proc mountit /sys mountit /dev/pts mountit /dev/shm # 5: initialize and startup mdev (simple replacemnt of udev) echo -en "Initializing mdev...\t\t\t\t" echo /sbin/mdev > /proc/sys/kernel/hotplug /sbin/mdev -s &> /dev/null check_status # 6: mount /tmp as RAM disk mountit /tmp chmod 1777 /tmp # 7: start system logger echo -en "Starting system logger...\t\t\t" start-stop-daemon -S -q -x syslogd check_status # 8: start up network interface echo -e "Enabling localhost interface...\t\t\t[done]" ifconfig lo up 127.0.0.1 route add 127.0.0.1 lo echo -e "Enabling network interface...\t\t\t[done]" ifconfig eth0 up $IP netmask $NETMASK route add default gw $GATEWAY # 9: start telnet daemon echo -en "Starting telnetd...\t\t\t\t" start-stop-daemon -S -q -x telnetd check_status # 10: mount all remaing file systems echo -en "Mounting user file systems...\t\t\t" mount -a &> /dev/null check_status # 11: print a logon screen echo echo echo "EmlinDist: Embedded linux distribution by Elvoris s.r.o." echo
Vysvětlivky (body odpovídají číslům v komentářích):
- Vytiskneme obsah souboru /etc/issue.rcs - úvodní obrazovku.
- Na místo původního adresáře /dev v RFS připojíme RAM disk. Tím jednak překryjeme původní obsah adresáře a hlavně bude možné vytvářet soubory zařízení za běhu systému bez ohledu na to, zda RFS je připojen v režimu jen pro čtení, či zda umožňuje i zápis. Tento krok vyžaduje správce souborů zařízení mdev (viz dále).
- V novém adresáři /dev v RAM disku vytvoříme adresáře /dev/pts a /dev/shm. První z nich je využíván pseudo terminály (telnetový klient, emulátor terminálu v X windows - xterm. atd.). Druhý pak pro meziprocesovou komunikaci.
- V této fázi připojíme všechny potřebné virtuální souborové systémy, které mohou být vyžadovány službami (démony) a procesy. Využijeme přitom uživatelskou funkci mountit() a záznamů v souboru /etc/fstab (viz dále), čímž si zkrátíme zápis příkazů.
- Inicializujeme správce souborů zařízení mdev. Nejprve jej zaregistrujeme k odběru událostí jádra generovaných při přidání zařízení, díky čemuž mdev pro každé přidané zařízení, které nalezne v svém konfiguračním souboru, vytvoří odpovídající soubor zařízení. A pak mu přikážeme, aby pro všechny zařízení detekované při startu systému, vytvořil soubory zařízení. Všimněme si použití funkce check_status, která nedělá nic jiného, než že ze proměnné shellu $? vyčte návratovou hodnotu posledního příkazu a podle toho zobrazí na systémové konzoli zprávu o úspěchu nebo selhání posledního příkazu.
- K adresáři tmp/ připojíme RAM disk a nastavíme mu potřebná práva přístupu.
- Spustíme systémovou službu (démona) syslogd, který vyčítá bufer zpráv z jádra (/proc/kmsg), přijímá zprávy z mnoha jiných programů, filtruje je a ukládá do souboru /var/log/messages. Využíváme k tomu utilitu start-stop-daemon, která je určena pro spouštění a zastavování systémových služeb (démonů).
- Nastavíme a spustíme (příkaz ifconfig) lokální síťové rozhraní (lokální síťová smyčku). Pak přidáme záznam do směrovací tabulky (příkaz route) pro tuto síť.Nastavíme a spustíme síťové rozhraní počítače. Uvedená IP adresa je IP adresou našeho počítače. Abychom mohli komunikovat mimo naši síť, musíme přidat výchozí směrovací tabulku s uvedením síťové brány, přes kterou je tato síť dosažitelná.
- Spustíme telnetový server, takže se bude možné k našemu počítači připojit pomocí telnetového klienta.
- Připojíme všechny zbývající souborové systémy, které jsou uvedeny v souboru /etc/fstab a které nebyly dosud připojeny.
- Zobrazíme přihlašovací obrazovku. Tím provádění inicializačního skriptu končí. Proces init otevře virtuální terminály a bude čekat na přihlášení uživatele (nebo rovnou spustí instanci shellu, pokud není přihlášení vyžadováno).
Skript /etc/init.d/rcK
Ukončovací skript /etc/init.d/rcK je procesem init volán v případě vypínání systému. Je víceméně opakem inicializačního skriptu /etc/init.d/rcS, byť ne všechny aktivity provedené inicializačním skriptem musí být explicitně v ukončovacím skriptu ukončeny.
Obsah souboru:
#!/bin/sh # /etc/init.d/rcK: The script called on shutdown # 1: print byebye message echo echo echo "Bye bye" echo # 2: stop services echo -e "Stopping daemons...\t\t\t[done]" start-stop-daemon -K -q -x syslogd start-stop-daemon -K -q -x telnetd # 3: flush disk buffers sync # 4: umount file systems if neccessary (CDROMs, hotplug, etc.) echo -e "Umounting file systems...\t\t[done]" umount -a -r 2>/dev/null
Vysvětlivky (body odpovídají číslům v komentářích):
- Zobrazíme zprávu u ukončování běhu systému
- Zastavíme všechny systémové služby, které běží.Poznámka: Pokud se pokusíme zastavit systémovou službu, která neběží, nic se nestane. Proto nemá smysl, řešit nějaký mechanismu, který by evidoval, která služba byla při startu systému spuštěna a která ne.
- Příkaz flush zajistí, že obsah všech buferů se zapíše na připojené harddisky.
- Posledním krokem je odpojení všech připojených souborových systémů. U těch, u kterých se to nepodaří (např. protože má nějaký program otevřený soubor), se příkaz umount pokusí je připojit v režimu pouze pro čtení. Odpojování souborových systému má zabránit porušení jejich konzistence.