от Theodor(21-10-2000)

рейтинг (7)   [ добре ]  [ зле ]

Printer Friendly Вариант за отпечатване

System-V разяснена

Geoffrey Bennett - 07/17/2000

Ще разгледаме инициализацията (init) и инициализационните System-V скриптове, използвани в повечето Linux дистрибуции.

Първата програма, която ядрото стартира, след като драйверите за устройства вече са заредени и root файловата система е монтирана е /sbin/init. Конфигурационният файл за init е /etc/inittab.

Всеки ред в inittab, който не е отбелязан като коментар (не започва с #) следва определен формат, който обяснява кои програми трябва да бъдат стартирани от init на всяко ниво на стартиране (runlevel). Форматът е идентификатор:ниво на стартиране:действие:програма. Всяко поле има специфично предназначение. Ето един примен inittab файл (по-скоро част от него)

# /etc/inittab
#
# Format of this file:
# identifier:runlevels:action:program

# Default runlevel.
id:3:initdefault:

# System initialisation.
si::sysinit:/etc/rc.d/rc.sysinit

l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6

# Run gettys in standard runlevels.
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6

# Run xdm in runlevel 5.
x:5:respawn:/etc/X11/prefdm -nodaemon

Полето на идентификатора предвижда от едно до четирибуквено име за съответния ред. Идентификаторът трябва да бъде уникален. Той обикновенно е съкращение на това какво представлява програмата или какво върши, но за getty процеса (който изкарва логин промпта на екрана ви) той трябва да съдържа името на терминала без първите tty букви. Например getty процеса, който стартира на първия сериен порт (/dev/ttyS0) ще бъде S0.

Полето runlevel изброява нивата на стартиране в които програмата ще се стартира. Например X дисплей мениджъра обикновенно е настроен да се стартира само в runlevel 5, но mingetty процесите обикновенно се използват в нива на стартиране 2, 3, 4 и 5.

Функциите, обикновенно свързани със всеки runlevel са следните:

0 halt - спиране работата на компютъра;
1 single user mode - еднопотребителски режим на работа;
2 multiuser, without NFS - многопотребителски режим на работа без NFS (Network File System);
3 full multiuser mode - пълен многопотребителски режим на работа;
4 unused - не се използва;
5 X11 - X11 (X Windows);
6 reboot - Рестартиране.

Пелето "действие" съдържа ключова дума (като respawn, wait, once), която показва как трябва да бъде стартирана програмата. Полето "програма" съдържа името на програмата, която трябва да бъде стартирана, а също и нейните аргументи (опции).

Ключовите думи на полето "действие" в inittab.

Най-интересната ключова дума на полето "действие" е respawn. Тя казва на init да стартира дадената програма в подходящия runlevel и да стартира друго копие, когато този процес завърши. Вие може да видите в inittab файла, че тази възможност се използва при mingetty процесите.

Преди да експериментирате с това действие проверете, дали е зареден логин промпта на втората виртуална конзола (отваря се с Alt-F2), след това се логнете в първата виртуална конзола (Alt-F1) и напишете ps auxw | grep tty2 . Ще видите стартиран процес, който изглежда така:

root 14718 0.0 0.6 1092 408 tty2 S 13:11 0:00
/sbin/mingetty tty2

Превключете на втората виртуална конзола и напишете своето име за логване, но все още не пишете паролата си. Превключете на първата конзола и стартирайте ps командата отново и ще видите резултат като този отдолу

root 14718 0.0 1.3 2108 868 tty2 S 13:11 0:00 /bin/login
--

Въпреки, че mingetty процесът е завършил, той е оставил след себе си нов логин процес със същия идентификационен номер на процеса (PID). Като процес със същия PID като първоначалния mingetty процес все още съществува init все още няма да стартира друг mingetty процес на тази конзола.

След това въведете паролата във втората виртуална конзола, повторете ps командата и ще видите нещо като това

root 14718 0.0 1.7 2232 1112 tty2 S 13:11 0:00 login --
geoffrey

geoffrey 14830 3.7 1.6 1208 432 tty2 S 13:25 0:00 -bash

Веднъж login да потвърди вашата парола той стартира вашия login shell (login обвивка - в случая bash). login процеса обикновенно съществува, докато не излезете (log out), но в някои случаи той ще замести себе си със вашата обвивка (по същия начин по който mingetty замества себе си с login). Процесът ще изглежда така.

root 14886 0.4 0.6 1092 408 tty2 S 13:33 0:00 /sbin/mingetty tty2

init е интелигентен в този смисъл, че ако забележи, че той рестартира същия процес процес той ще го дезактивира за няколко минути. Това ще помогне да се предпази системата от твърде голямо натоварване, в случай, че програмата, която init трябва да рестартира не работи коректно. Това се случва обикновенно, когато вие напишете погрешно името на програмата в /etc/inittab, или когато изтриете програма, към която има обръщение в inittab.

За да видите това лично натиснете 10 пъти Ctrl+D, когато се намирате на login промпта. Вие трябва да видите съобщение като долното, което означава, че за известно време няма да имате login промпт.

INIT: Id "2" respawning too fast: disabled for 5 minutes

Ако някога получите такова съобщение може да не искате да чакате 5 минути, докато init опита отново ( например ако сте поправили проблема, който кара програмата да се затваря толкова бързо). В този случай напишете следното kill -1 1 или /sbin/telinit q. Написаното играе ролята на команда за init да прочете отново своя конфигурационен файл и да активира всички програми, които преди това са били дезактивирани.

Действието wait в /etc/inittab ще стартира дадената програма и init ще изчака, докато завърши изпълнението на програмата. За разлика от respawn, когато работата на програмата завърши тя няма да бъде стартирана отново. В нашият примерен inittab wait се използва за стартирането на скрипта /etc/rc.d/rc, който е ключова част от инициализиращите Sistem V скриптове.

Действието sysinit се отнася за програма, която трябва да бъде стартирана само веднъж при стартирането на системата (програмите ще се стартират преди някое отделно ниво на стартиране (runlevel)). При sysinit дейстивето списъкът с нивата на стартиране се оставя празен, защото тук той не е нужен.

Най-накрая действието initdefault дефинира стандартното ниво на стартиране за вашата система. Името на програмата се игнорира и трябва да бъде оставено празно.

Горните примери илюстрират най-основните действия. За повече информация вижте man страницата inittab(5).

init.d скриптове и услуги

Въпреки, че init може да бъде използван за стартиране и спиране на услуги (такива като xdm) съществува по-удобен метод, който се използва за повечето от другите услуги; това е схемата на инициализационни скриптове на System-V.

Първата част от тази схема е, че един скрипт в /etc/rc.d/init.d директорията (/etc/init.d в някои дистрибуции) се пази за всяка услуга и всеки скрипт трябва да може да приема един аргумент - start или stop. Например, ако бихте искали да спрете принтерската услуга (lpd) веднага, вие трябва да можете да напишете
/etc/rc.d/init.d/lpd stop

Всеки скрипт ще приема start и stop като параметри, но за повечето услуги има и други налични параметри.

status

Този параметър съобщава дали е стартирана или не тази услуга. За услуги с повече от един демон (daemon) (както NFS, който има демон за маунтване, демон за квоти, а също така и главен NFS демон) параметърът status ви показва състоянието на всеки демон.

restart

Това е съкратена команда за спиране и отново стартиране на услугата.

reload

Този параметър дава команда на услугата да прочете отново конфигурационния си файл. В много случаи е препоръчително е да се използва reload вместо restart. Така се избягва краткия период, в който услугата не е стартирана.

The /etc/rc.d/rcx.d directories

Директориите /etc/rc.d/rcx.d са следващата част от схемата на инициализационни скриптове на System-V. Тук х се отнася до конкретен runlevel (от 0 до 6) (някои дистрибуции държът тези скриптове в директория /etc/rcx.d).

Да разгледаме /etc/rc.d/rc3.d директорията.

ls -la
total 2
drwxr-xr-x 2 root root 1024 Apr 30 12:50 .
drwxr-xr-x 10 root root 1024 Apr 26 13:28 ..
lrwxrwxrwx 1 root root 13 Feb 26 1998 K15gpm -> ../init.d/gpm
lrwxrwxrwx 1 root root 15 Jan 16 18:57 K35dhcpd -> ../init.d/dhcpd
lrwxrwxrwx 1 root root 13 Apr 26 14:01 K35smb -> ../init.d/smb
lrwxrwxrwx 1 root root 15 Jun 2 1999 K50snmpd -> ../init.d/snmpd
lrwxrwxrwx 1 root root 13 Feb 26
1998 K60lpd -> ../init.d/lpd
lrwxrwxrwx 1 root root 14 Nov 11 1998 S05apmd -> ../init.d/apmd
lrwxrwxrwx 1 root root 17 Feb 3 1998 S10network -> ../init.d/network
lrwxrwxrwx 1 root root 16 Feb 3 1998 S20random -> ../init.d/random
lrwxrwxrwx 1 root root 15 Apr 26 13:28 S25netfs -> ../init.d/netfs
lrwxrwxrwx 1 root root 16 Feb 3 1998 S30syslog -> ../init.d/syslog
lrwxrwxrwx 1 root root 13 Feb 2 1999 S40atd -> ../init.d/atd
lrwxrwxrwx 1 root root 15 Feb 3 1998 S40crond -> ../init.d/crond
lrwxrwxrwx 1 root root 16 Jun 2 1999 S45pcmcia -> ../init.d/pcmcia
lrwxrwxrwx 1 root root 14 Apr 26 13:43 S50inet -> ../init.d/inet
lrwxrwxrwx 1 root root 18 Apr 26 13:28 S75keytable -> ../init.d/keytable
lrwxrwxrwx 1 root root 18 Feb 3 1998 S80sendmail -> ../init.d/sendmail
lrwxrwxrwx 1 root root 15 Jul 1 1999 S85httpd -> ../init.d/httpd
lrwxrwxrwx 1 root root 15 Feb 3 1998 S85sound -> ../init.d/sound
lrwxrwxrwx 1 root root 13 Jun 2 1999 S90xfs -> ../init.d/xfs
lrwxrwxrwx 1 root root 11 Feb 3 1998 S99local -> ../rc.local

Тук има много символни връзки, всяка от които сочи към един от скриптовете в init.d директорията. Когато преминаваме към нов runlevel имената на символните връзки се използват за да се определи кои конкретни услуги трябва да бъдат стартирани или спряни и в какъв ред (например мрежовата услуга е необходима за повечето от останалите услуги и затова трябва да бъде стартирана по-рано).

Името на символната връзка трябва да отговаря на следния формат.

  • S (за 'Start') или K (за 'Kill') за стартиране или спиране на услугата в този runlevel

  • Двуцифрено число, чрез което се определя реда в който се появяват услугите (малките числа се стартират и спират преди големите числа)

  • Име на услугата, за да е сигурно, че имената са уникални.
  • Напиример символната връзка S05apmd, която е първата връзка намираща се в директория /etc/rc.d/rc3.d означава че apmd ще бъде първата услуга, която ще се стартира при преминаване към runlevel 3.

    Възможно е (макар и да е досадно) тези символни връзки да се променят ръчно. Например, ако решите да стартирате lpd в runlevel 3 вие може да напишете следното.

    mv /etc/rc.d/rc3.d/K60lpd \

    /etc/rc.d/rc3.d/S40lpd.

    По-малко досаден метод за манипулиране на символни връзки е да се използва програмата chkconfig написана от Red Hat. Например, за да видите нивата в които услугата е активирана напишете $ /sbin/chkconfig --list lpd и трябва да получите нещо като lpd 0:off 1:off 2:off 3:off 4:off 5:off 6:off. За да стартирате lpd услугата в тези нива, където тя е най-много необходима напишете $ /sbin/chkconfig --list lpd on. Препотвърдете отново с опцията --list и вие трябва да видите, че lpd е активирана за нива на стартиране 3, 4 и 5.

    rc скриптът

    Финалната част от System-V инициализационните скриптове е rc скрипта, който представлява малък скрипт, който следи символните връзки и стартира скриптовете в init.d директорията.

    /etc/rc.d/rc скрипта се стартира на всеки runlevel, с параметър показващ в кое ниво на стартиране сме навлезли. Използвайки тази информация и символната връзка в подходящата дирекпория е въпрос на съвсем просто shell програмиране (използвайки командите на bash или друга обвивка) да се извърши подходящото действие.

    Истинският rc скрипт също така ще проверява, дали не се опитва да стартира вече стартирана услуга или да спира услуга, която не е стартирана.

    #!/bin/sh

    # Get the new runlevel
    runlevel=$1

    # Run the ‘Kill’ scripts
    for i in /etc/rc.d/rc$runlevel.d/K*; do
    $i stop
    done

    # Run the ‘Start’ scripts
    for i in /etc/rc.d/rc$runlevel.d/S*; do
    $i start
    done

    Първата част от скрипта поставя първия аргумент в променливата runlevel, която е достъпна чрез $runlevel. Първият цикъл взима всички К скриптове от съответната runlevel директория и ги стартира със аргумент stop. Вторият цикъл извиква S скриптовете със stаrt аргумент.

    Ако не сте виждали как се използва цикъл в обвивката няколко прости примера могат да ви бъдат от полза. Напишете следната команда на промпта на обвивката.

    for i in fred bob sam; do

    echo $i

    done

    Обвивката ще повтори частта между do и done три пъти и всеки път тя ще дава стойност на променливата $i съответно fred, bob и sam. Частта между in и do не е задължително да е фиксиран списък. Може да използвата звездички, за да генерирате списък от файлови имена. За да опитате да го направите използвайте echo командата по-долу.

    echo /etc/rc.d/rc3.d/K*

    echo /etc/rc.d/rc3.d/S*

    runlevel=3

    echo /etc/rc.d/rc$runlevel.d/K*

    echo /etc/rc.d/rc$runlevel.d/S*


    << Win NT vs. Linux! | Ръководство за намиране на помощна инфoрмация в Linux >>