© Alec Voropay, FDL
Довольно часто задаваемый вопрос : Каким образом стартует система ? Где в Linux аналог autoexec.bat ?
Чтобы понять, как стартует система, сначала необходимо понять идею RunLevel-а.
Для нетерпеливых - быстрый ответ.
Как написано в man init : RunLevel - это "особая конфигурация системы, при которой существуют только определенные группы процессов". Существуют RunLevel-ы от "0" до "6" и особый RunLevel "S" (single user).
Итак, для RedHat :
Идея RunLevel-ов пошла из системы UNIX System V и POSIX и поэтому Linux-ы (и RedHat в том числе) используют именно SYSV init. В других системах (например *BSD) используются совершенно другие понятия и процесс старта/останова системы совсем другой.
ПРИМЕЧАНИЕ : Такая раскладка по RunLevel-ам принята именно в RedHat Linux. В других дистрибутивах может быть принята другая схема.
ПРИМЕЧАНИЕ : В данном тексте совершенно не рассматривается вопрос, как стартует само ядро Linux (MBR, LILO/GRUB, init-rd и так далее). Считается, что ядро "как-то" загрузилось и взлетело. ;)
Процесс init - совершенно особый процесс в любой системе UNIX. Во-первых, он всегда имеет PID=1. Во-вторых, он не имеет предков и порождается совершенно "чудесным" образом прямо после старта ядра UNIX. В третьих, init - это "папа", "дедушка" или "пра-пра-дедушка" всех процессов в системе.
Эти правила общие для любой системы UNIX, мы же будем рассматривать только SYSV init.
Сразу после старта init
читает файл /etc/inittab
. Нас заинтересуют
следующие строки :
id:3:initdefault: l3:3:wait:/etc/rc.d/rc 3
Это означает, что RunLevel
по умолчанию будет 3, и для запуска
его необходимо выполнить исполняемый файл /etc/rc.d/rc
с параметром "3".
А если необходимо, чтобы система стартовала
прямо в X-ах, можно поменять RunLevel
на "5".
В любой момент можно
сменить текущий RunLevel, для
этого просто нужно дать команду "init
3" или например "init
6". При каждой смене Run-Level-а
исполняется файл /etc/rc.d/rc 3 (или
6).
Файл /etc/rc.d/rc
довольно
интересен. Он показывает всю мощь языка shell.
Ключевые строки в нем следующие :
for i in /etc/rc.d/rc$runlevel.d/K*; do $i stop done for i in /etc/rc.d/rc$runlevel.d/S*; do $i start done
Надеюсь, все понятно ? ;-) См. быстрый ответ. Но сначала рассмотрим, что такое "подсистемы".
ПРИМЕЧАНИЕ : На
самом деле можно запустить совершенно
любую программу вместо init
:
LILO: linux init=/bin/bash
#
Кто там спрашивал, как сломать Linux ? ;) (не
забудьте mount -n -o rw,remount / )
[используйте пароль на GRUB или LILO]
В системе RedHat все
демоны (группы процессов) разделены на "подсистемы".
Например sendmail, или named. Файлы для
запуска "подсистем" живут в /etc/rc.d/init.d/*
Так что если вы хотите правильно, "по-RedHat-овски" запустить или остановить какой-нибудь демон, действовать надо так :
[root@on ~]# /etc/rc.d/init.d/sendmail start [root@on ~]# /etc/rc.d/init.d/sendmail stop
Для облегчения жизни существует команда service :
[root@on ~]# service sendmail start [root@on ~]# service sendmail stop
Или проще, для перезапуска "подсистемы" :
[root@on ~]# service sendmail restart
Кроме того, в любой момент можно узнать статус "подсистемы" :
[root@on ~]# service sendmail status sendmail (pid 186) is running...
Все запущенные "подсистемы"
регистрируются в /var/lock/subsys/
Документация в /usr/share/doc/initscripts/sysvinitfiles
или тут.
В RedHat для быстрого
управления RunLevel-ами существует
специальная утилита : ntsysv
.
С ее помощью можно быстро "включать" и
"отключать" различные подсистемы на
разных уровнях. По умолчанию, она работает с
текущим RunLevel-ом.
Более простая, но более широко
распространенная утилита : chkconfig
.
Однако, только chkconfig умеет
"регистрировать"
новые
подсистемы с помощью ключей --add --del. См. man
chkconfig.
Под X Window существует утилита
аналогичного назначения: tksysv
.
Чтобы понять, как это все
работает на "низком уровне", заглянем в
каталог /etc/rc.d/rc3.d/
[root@on ~]# cd /etc/rc.d/rc3.d/ [root@on rc3.d]# ls -l lrwxrwxrwx 1 root root 16 Feb 7 19:30 K20rstatd -> ../init.d/rstatd lrwxrwxrwx 1 root root 17 Feb 7 19:30 K20rusersd -> ../init.d/rusersd lrwxrwxrwx 1 root root 15 Feb 7 19:30 K20rwhod -> ../init.d/rwhod lrwxrwxrwx 1 root root 15 Feb 8 16:48 K45named -> ../init.d/named lrwxrwxrwx 1 root root 16 Feb 7 19:29 K55routed -> ../init.d/routed lrwxrwxrwx 1 root root 17 Feb 7 19:19 S10network -> ../init.d/network lrwxrwxrwx 1 root root 16 Feb 7 19:19 S20random -> ../init.d/random lrwxrwxrwx 1 root root 16 Feb 7 19:19 S30syslog -> ../init.d/syslog lrwxrwxrwx 1 root root 13 Feb 7 19:20 S40atd -> ../init.d/atd lrwxrwxrwx 1 root root 15 Feb 7 19:19 S40crond -> ../init.d/crond lrwxrwxrwx 1 root root 14 Feb 7 19:27 S50inet -> ../init.d/inet lrwxrwxrwx 1 root root 15 Feb 8 17:00 S55named -> ../init.d/named lrwxrwxrwx 1 root root 18 Feb 7 19:19 S75keytable -> ../init.d/keytable lrwxrwxrwx 1 root root 18 Feb 7 19:30 S80sendmail -> ../init.d/sendmail lrwxrwxrwx 1 root root 13 Feb 7 19:24 S85gpm -> ../init.d/gpm lrwxrwxrwx 1 root root 13 Feb 7 19:19 S90xfs -> ../init.d/xfs lrwxrwxrwx 1 root root 19 Feb 7 19:26 S99linuxconf -> ../init.d/linuxconf lrwxrwxrwx 1 root root 11 Feb 7 19:19 S99local -> ../rc.local
Опять выполняется правило, общее для RedHat - Все живет на symlink-ах !
Как мы выяснили ранее,
выполнение скрипта /etc/rc.d/rc 3
вызовет
: для всех symlink-ов с буквой "К"
вызов подсистем с параметром 'stop',
а для symlink-ов с буквой "S"
-- подсистем с параметром "start".
А цифры служат для лишь для указания порядка выполнения скриптов. (А на самом деле, работает просто звездочка * из shell).
Как несложно догадаться, RunLevel
6 /etc/rc.d/rc6.d/
(останов
системы) состоит практически из одних "K*"
(то есть, убивает все процессы).
Довольно часто задают вопрос : зачем это все так сложно ?
Ответ обескураживает - Для простоты !
Дело в том, что при таком раскладе можно очень просто администрировать, какие подсистемы и в каком порядке будут запущены и остановлены на каком RunLevel-е.
Действительно, нужно лишь
поставить нужный symlink, не изменяя и
не редактируя никаких файлов. (Вообще
говоря, утилита ntsysv
именно это и делает. Только не забудьте "зарегистрировать"
подсистему через chkconfig --add
service
).
Например, чтобы "вручную" добиться автоматического запуска на RunLevel 3 подсистемы sshd нужно лишь поставить symlink :
/etc/rc.d/rc3.d/S75sshd --> ../init.d/sshd
Причем, мы можем точно
контролировать, когда (после каких
подсистем) он запустится. Да, а на RunLevel 6
(/etc/rc.d/rc6.d/
) надо не забыть поставить K25sshd
.
Однако удалять synlink-и вручную нет необходимости, поскольку с помощью утилит делать это проще и кроме того, сохраняется связность скриптов Start/Kill.
Управлять порядком запуска/останова "подсистем" можно через ключевое слово # chkconfig: 235 94 06 в .init файлах. См. документацию тут.