|
1.
Уровни запуска
Процесс загрузки системы
При загрузке вашей системы по экрану пробегает много текста. Если
присмотреться, заметно, что этот текст не меняется от загрузки к загрузке.
Последовательность всех этих действий называется последовательностью
загрузки и в той или иной степени постоянна.
Во-первых, загрузчик размещает в памяти образ ядра, который вы указали в
файле его конфигурации. После этого ядро запускается. Когда ядро загружено и
запущено, оно инициализирует относящиеся к ядру структуры и задания, и
запускает процесс init.
Этот процесс удостоверяется, что все файловые системы (определенные в
/etc/fstab) смонтированы и готовы к использованию. Затем он
выполняет несколько сценариев, находящихся в каталоге /etc/init.d,
которые запускают службы, необходимые для нормального запуска системы.
И, наконец, когда все сценарии выполнены, init подключает терминалы
(чаще всего просто виртуальные консоли, которые видны при нажатии
ALT+F1, ALT+F2 и т.д.), прикрепляя к каждой консоли специальный
процесс под названием agetty. Этот процесс впоследствии обеспечивает
возможность входа в систему с помощью login.
Сценарии инициализации
Сейчас процесс init запускает сценарии из каталога
/etc/init.d не просто в случайном порядке. Более того, запускаются
не все сценарии из /etc/init.d, а только те, которые предписано
исполнять. Решение о запуске сценария принимается в результате просмотра
каталога /etc/runlevels.
Во-первых, init запускает все сценарии из /etc/init.d, на
которые есть символьные ссылки из /etc/runlevels/boot. Обычно
сценарии запускаются в алфавитном порядке, но в некоторых сценариях имеется
информация о зависимостях от других сценариев, указывающая системе на
необходимость их предварительного запуска.
Когда все сценарии, указанные в /etc/runlevels/boot, будут
выполнены, init переходит к запуску сценариев, на которые есть
символьные ссылки из /etc/runlevels/default. И снова запуск
происходит в алфавитном порядке, пока в сценарии не встретится информация о
зависимостях; тогда порядок изменяется для обеспечения правильного порядка
запуска.
Как работает init
Конечно, init не принимает решений сам по себе. Ему необходим
конфигурационный файл, где описаны необходимые действия. Этот файл —
/etc/inittab.
Если вы запомнили последовательность загрузки, описанную чуть ранее, вы
вспомните, что первое действие init — это монтирование всех файловых
систем. Это определяется в строке /etc/inittab, приведенной ниже:
Листинг 1.1: Строка инициализации системы из /etc/inittab |
si::sysinit:/sbin/rc sysinit
|
Этой строкой процессу init предписывается выполнить /sbin/rc
sysinit для инициализации системы. Самой инициализацией занимается
сценарий /sbin/rc, так что можно сказать, что init делает
не слишком много — он просто делегирует задачу по инициализации системы
другому процессу.
Во-вторых, init выполняет все сценарии, на которые есть символьные
ссылки из /etc/runlevels/boot. Это определяется следующей строкой:
Листинг 1.1: Инициализация системы, продолжение |
rc::bootwait:/sbin/rc boot
|
И снова все необходимые действия выполняются сценарием rc. Заметьте, что
параметр, переданный rc (boot), совпадает с названием
используемого подкаталога в /etc/runlevels.
Теперь init проверяет свой конфигурационный файл, чтобы определить,
какой уровень запуска использовать. Для этого из
/etc/inittab считывается строка:
Листинг 1.1: Строка initdefault |
id:3:initdefault:
|
В приведенном примере (который подходит для подавляющего большинства
пользователей Gentoo) номер уровня запуска — 3. Пользуясь этой
информацей, init проверяет, что нужно выполнить для запуска уровня
запуска 3:
Листинг 1.1: Определение уровней запуска |
l0:0:wait:/sbin/rc shutdown
l1:S1:wait:/sbin/rc single
l2:2:wait:/sbin/rc nonetwork
l3:3:wait:/sbin/rc default
l4:4:wait:/sbin/rc default
l5:5:wait:/sbin/rc default
l6:6:wait:/sbin/rc reboot
|
В строке, определяющей уровень 3, для запуска служб снова используется сценарий
rc (на этот раз с аргументом default). Опять-таки, обратите
внимание, что аргумент, передаваемый сценарию rc, совпадает с названием
подкаталога из /etc/runlevels.
По окончании работы rc, init принимает решение о том, какие
виртуальные консоли включить и какие команды выполнить в каждой из них:
Листинг 1.1: Определение виртуальных консолей |
c1:12345:respawn:/sbin/agetty 38400 tty1 linux
c2:12345:respawn:/sbin/agetty 38400 tty2 linux
c3:12345:respawn:/sbin/agetty 38400 tty3 linux
c4:12345:respawn:/sbin/agetty 38400 tty4 linux
c5:12345:respawn:/sbin/agetty 38400 tty5 linux
c6:12345:respawn:/sbin/agetty 38400 tty6 linux
|
Что такое уровень запуска?
Как вы заметили, init применяет нумерацию для определения уровня
запуска, который надо использовать. Уровень запуска — это то
состояние, в котором запускается ваша система, он содержит набор
сценариев (сценариев уровня запуска или сценариев инициализации
[initscript]), которые следует выполнять, при входе и выходе из
определенного уровня запуска.
В Gentoo определено семь уровней запуска: три служебных и четыре
определяемых пользователем. Служебные называются sysinit,
shutdown и reboot. Действия, совершаемые ими, в точности
соответствуют их названиям: инициализация системы, выключение системы и ее
перезагрузка.
Определяемые пользователем уровни — это те, которым соответствуют
подкаталоги в /etc/runlevels: boot,
default, nonetwork и single. Уровень
boot запускает все службы, необходимые системе и используемые
всеми остальными уровнями. Остальные уровни отличаются друг от друга
запускаемыми службами: default используется для повседневной
работы, nonetwork — для тех случаев, когда не требуется
сеть, а single — при необходимости восстановления системы.
Работа со сценариями инициализации
Сценарии, запускаемые процессом rc, называются сценариями
инициализации. Каждый сценарий из /etc/init.d может
запускаться с аргументами start, stop, restart,
pause, zap, status, ineed, iuse,
needsme, usesme и broken.
Для запуска, остановки или перезапуска службы (и всех, зависящих от нее)
следует использовать start, stop и restart:
Листинг 1.1: Запуск postfix |
# /etc/init.d/postfix start
|
Примечание:
Останавливаются или перезапускаются только те службы, которым необходима
данная служба. Остальные зависимые службы (те, которые используют
службу, но не нуждаются в ней) эта операция не затрагивает.
|
Если вы хотите остановить службу, но оставить зависимые от нее работающими,
можно использовать аргумент pause:
Листинг 1.1: Остановка postfix без остановки зависимых служб |
# /etc/init.d/postfix pause
|
Чтобы узнать текущее состояние службы (запущена, остановлена,
приостановлена и т.д.), можно использовать аргумент status:
Листинг 1.1: Информация о состоянии postfix |
# /etc/init.d/postfix status
|
Если указано, что служба работает, но вы знаете, что это не так, можно сбросить
состояние на stopped (остановлена), используя аргумент zap:
Листинг 1.1: Сброс информации о состоянии postfix |
# /etc/init.d/postfix zap
|
Для того, чтобы выяснить зависимости службы, можно использовать аргументы
iuse или ineed. С помощью ineed вы увидите те службы,
которые действительно необходимы для правильного функционирования интересующей
вас службы. С другой стороны, iuse покажет те службы, которые могут
использоваться нашей службой, но не обязательны для ее работы.
Листинг 1.1: Запрос списка всех необходимых служб, от которых зависит Postfix |
# /etc/init.d/postfix ineed
|
Аналогично вы можете узнать, какие службы нуждаются в данной службе
(needsme) или могут ее использовать (usesme):
Листинг 1.1: Запрос списка всех служб, которым необходим Postfix |
# /etc/init.d/postfix needsme
|
Наконец, можно просмотреть список служб, требующихся для данной, но
отсутствующих в системе:
Листинг 1.1: Запрос списка служб, необходимых Postfix, но отсутствующих |
# /etc/init.d/postfix broken
|
1.
Использование rc-update
Что такое rc-update?
Система инициализации Gentoo использует дерево зависимостей для определения
служб, которые запускаются в первую очередь. Т. к. это очень утомительное
занятие, и мы не хотели, чтобы пользователь занимался этим вручную, мы
разработали инструменты, упрощающие управление уровнями запуска и сценариями
инициализации.
Используя rc-update, можно включать и исключать сценарии инициализации
из уровней запуска. Из rc-update автоматически запускается сценарий
depscan.sh для перестроения дерева зависимостей.
Добавление и удаление служб
В процессе установки Gentoo вы уже добавляли сценарии инициализации в уровень
запуска «default». В тот момент вы, возможно, не имели понятия, что
такое «default» и зачем он нужен, но теперь вы все это знаете.
Сценарию rc-update требуется второй аргумент, определяющий действие:
add (добавить), del (удалить) или show (показать).
Для того, чтобы добавить или удалить сценарий, просто введите rc-update
с аргументом add или del, затем название сценария и уровня
запуска. Например:
Листинг 1.1: Удаление Postfix из уровня запуска default |
# rc-update del postfix default
|
По команде rc-update show выводится список всех доступных сценариев с
указанием соответствующих уровней запуска:
Листинг 1.1: Получение информации о сценариях инициализации |
# rc-update show
|
1.
Настройка служб
Почему нужна дополнительная настройка?
Сценарии инициализации могут быть весьма сложны. Поэтому нежелательно допускать
непосредственное редактирование сценария пользователями, т.к. это может
привнести в систему множество ошибок. Но, с другой стороны, необходимо
правильно настроить службу. Например, может понадобиться передать службе
дополнительные параметры.
Вторая причина, по которой настройки хранятся отдельно от самого сценария
— это возможность обновления сценария без опасения, что все ваши
настройки будут утеряны.
Каталог /etc/conf.d
В Gentoo предусмотрен очень простой способ настройки служб: для каждого
сценария, предполагающего настройку, в каталоге /etc/conf.d
есть конфигурационный файл. Например, у сценария, запускающего apache2
(под названием /etc/init.d/apache2) есть конфигурационный файл
/etc/conf.d/apache2, где могут храниться нужные вам параметры,
передаваемые серверу Apache 2 при запуске:
Листинг 1.1: Переменная, определенная в /etc/conf.d/apache2 |
APACHE2_OPTS="-D PHP4"
|
Такие файлы настроек содержат одни переменные (наподобие
/etc/make.conf), облегчая настройку служб. Это также позволяет нам
давать больше информации о переменных (в комментариях).
1.
Написание сценариев инициализации
Мне тоже придется?..
Нет, написание сценариев инициализации обычно не требуется, т.к. Gentoo
содержит готовые сценарии для всех поддерживаемых служб. Однако, вы можете
установить какую-либо службу, не используя систему Portage; в таком случае,
вероятно, вам придется создавать сценарий инициализации самостоятельно.
Не используйте сценарий, идущий со службой, если он не написан специально для
Gentoo: сценарии инициализации Gentoo не совместимы со сценариями,
используемыми в других дистрибутивах!
Структура
Основная структура сценария инициализации показана ниже.
Листинг 1.1: Основная структура сценария |
#!/sbin/runscript
depend() {
}
start() {
}
stop() {
}
restart() {
}
|
В любом сценарии должна быть определена функция start(). Все
остальные разделы необязательны.
Зависимости
Можно определять два типа зависимостей: use (использую) и need
(нуждаюсь). Как упоминалось ранее, need-зависимость более строга, чем
use-зависимость. Вслед за типом зависимости указывается название службы,
от которой существует зависимость, или ссылка на виртуальную (virtual)
зависимость.
Виртуальная зависимость — это зависимость от функций,
предоставляемых службой, но не какой-то единственной службой. Сценарий может
зависеть от службы системного журнала, но таких достаточно много (metalogd,
syslog-ng, sysklogd и т.п.). Поскольку нельзя нуждаться в каждой из них
(ни в одной вразумительной системе они не запущены все сразу), мы обеспечили
предоставление виртуальной зависимости всеми этими службами.
Давайте взглянем на информацию о зависимостях postfix.
Листинг 1.1: Информация о зависимостях Postfix |
depend() {
need net
use logger dns
provide mta
}
|
Как можно увидеть, postfix:
-
требует сеть (net): виртуальная зависимость, удовлетворяемая,
например, /etc/init.d/net.eth0
-
использует журнал (logger): виртуальная зависимость,
удовлетворяемая, например, /etc/init.d/syslog-ng
-
использует службу имен (dns): виртуальная зависимость,
удовлетворяемая, например, /etc/init.d/named)
-
предоставляет почтовый агент (mta): виртуальная зависимость,
общая для всех программ — почтовых серверов
Порядок запуска
Иногда вам нужна не сама служба, а запуск вашей службы до (или
после) другой службы, если та присутствует в системе
(обратите внимание на условие: это уже не зависимость) и запускается
на том же уровне запуска (отметьте условие: это относится только к службам
из одинакового уровня запуска). Такую очередность можно указать, используя
значения before (до) или after (после).
Например, рассмотрим значения для службы Portmap:
Листинг 1.1: Функция depend() службы Portmap |
depend() {
need net
before inetd
before xinetd
}
|
Также можно использовать знак «*«, чтобы охватить все службы
данного уровня запуска, хотя это не рекомендуется.
Листинг 1.1: Запуск сценария первым на уровне запуска |
depend() {
before *
}
|
Стандартные функции
Следом за разделом depend() вам потребуется определить функцию
start(). В ней содержатся все команды, необходимые для запуска вашей
службы. Рекомендуется применять функции ebegin и eend для
сообщений пользователю о том, что происходит:
Листинг 1.1: Пример функции start() |
start() {
ebegin "Запуск - моя_служба"
start-stop-daemon --start --quiet --exec /path/to/my_service
eend $?
}
|
Если вам нужны дополнительные примеры функции start(), пожалуйста,
прочитайте исходные коды сценариев инициализации, находящихся в каталоге
/etc/init.d. Что касается команды start-stop-daemon, то
на случай, если вам нужны дополнительные сведения, есть превосходная
страница справки:
Листинг 1.1: Вызов страницы справки по start-stop-daemon |
# man start-stop-daemon
|
Другими функциями, которые можно определить — stop() и
restart(). От вас не требуется определение этих функций! Система
инициализации, применяемая нами, достаточно развита и в состоянии
самостоятельно заполнить эти функции, если вы используете
start-stop-daemon.
Синтаксис сценариев инициализации, применяемых в Gentoo, основан на
оболочке Борна (Bourne Again Shell — bash), поэтому вы можете свободно
использовать внутри своих сценариев bash-совместимые конструкции.
Добавление дополнительных параметров
Если вы хотите ввести в сценарий дополнительные параметры, кроме упоминавшихся,
нужно добавить к переменной opts название параметра и создать функцию
с названием, соответствующим параметру. Например, для поддержки параметра
restartdelay:
Листинг 1.1: Создание дополнительной функции restartdelay |
opts="${opts} restartdelay"
restartdelay() {
stop
sleep 3
start
}
|
Переменные для настройки служб
Для поддержки конфигурационного файла в каталоге /etc/conf.d
ничего дополнительно делать не нужно: при запуске вашего сценария инициализации
автоматически включаются следующие файлы (т.е., переменные из них становятся
доступны):
- /etc/conf.d/<ваш сценарий инициализации>
- /etc/conf.d/basic
- /etc/rc.conf
Если ваш инициализационный сценарий предоставляет виртуальную зависимость
(например, net), то также включается файл, соответствующий этой
зависимости (например, /etc/conf.d/net).
1.
Изменение поведения уровней запуска
Кто от этого выиграет?
Большинству пользователей ноутбуков знакома ситуация: дома вам нужен запуск
net.eth0, и наоборот, в дороге запуск net.eth0 не нужен (так как
сеть недоступна). В Gentoo можно изменять поведение уровней запуска по своему
усмотрению.
Например вы можете создать второй загружаемый уровень запуска «по
умолчанию», в котором будут другие сценарии. Затем при загрузке вы
сможете выбрать, какой из уровней по умолчанию следует использовать.
Использование программного уровня (softlevel)
Прежде всего, создайте каталог для своего второго уровня запуска «по
умолчанию». Например, создадим уровень запуска offline:
Листинг 1.1: Создание каталога уровня запуска |
# mkdir /etc/runlevels/offline
|
Добавьте необходимые сценарии инициализации в только что созданный уровень
запуска. Например, чтобы получить точную копию уровня default, за
исключением net.eth0:
Листинг 1.1: Добавление нужных сценариев инициализации |
# cd /etc/runlevels/default
# for service in *; do rc-update add $service offline; done
# rc-update del net.eth0 offline
# rc-update show offline
acpid | offline
domainname | offline
local | offline
net.eth0 |
|
Теперь необходимо отредактировать конфигурацию загрузчика, добавив запись об
уровне offline. Например, в файле /boot/grub/grub.conf:
Листинг 1.1: Добавление записи об уровне offline |
title Автономное использование Gentoo Linux
root (hd0,0)
kernel (hd0,0)/kernel-2.4.25 root=/dev/hda3 softlevel=offline
|
Вуаля, все готово. Теперь, если при загрузке вы выберете вновь созданную
запись, то вместо default будет использоваться уровень offline.
Использование загрузочного уровня (bootlevel)
Использование загрузочного уровня полностью аналогично использованию
программного уровня. Единственная разница состоит в том, что вы
определяете второй уровень «boot» вместо «default».
|