Handbook:Parts/Working/Initscripts/ru

Процесс загрузки системы
При загрузке вашей системы по экрану пробегает много текста. Если присмотреться, заметно, что обычно этот текст не меняется от загрузки к загрузке. Последовательность всех этих действий называется последовательностью загрузки и в той или иной степени постоянна.

Во-первых, загрузчик размещает в памяти образ ядра, который вы указали в файле его конфигурации. После этого начальный загрузчик просит процессор запустить ядро. Когда ядро загружено и запущено, оно инициализирует относящиеся к ядру структуры и задания, и запускает процесс init.

Этот процесс удостоверяется, что все файловые системы (определенные в ) смонтированы и готовы к использованию. Затем он выполняет несколько сценариев, находящихся в каталоге, которые запускают службы, необходимые для нормального запуска системы.

И, наконец, когда все сценарии выполнены, init подключает терминалы (чаще всего просто виртуальные консоли, которые видны при нажатии, и т.д.), прикрепляя к каждой консоли специальный процесс под названием. Этот процесс впоследствии обеспечивает возможность входа в систему через эти терминалы с помощью login.

Сценарии инициализации
Сейчас процесс init запускает сценарии из каталога не просто в случайном порядке. Более того, запускаются не все сценарии из, а только те, которые предписано исполнять. Решение о запуске сценария принимается в результате просмотра каталога.

Во-первых, init запускает все сценарии из, на которые есть символьные ссылки из. Обычно сценарии запускаются в алфавитном порядке, но в некоторых сценариях имеется информация о зависимостях от других сценариев, указывающая системе на необходимость их предварительного запуска.

Когда все сценарии, указанные в, будут выполнены, init переходит к запуску сценариев, на которые есть символьные ссылки из. И снова запуск происходит в алфавитном порядке, пока в сценарии не встретится информация о	зависимостях; тогда порядок изменяется для обеспечения правильного порядка запуска. Именно по данной причине команды, используемые во время установки Gentoo Linux, используют default, как в команде.

Как работает init
Конечно, init не принимает решений сам по себе. Ему необходим конфигурационный файл, где описаны необходимые действия. Этот файл -.

Если вы запомнили последовательность загрузки, описанную чуть ранее, вы вспомните, что первое действие init - это монтирование всех файловых систем. Это определяется в следующей строке файла :

Этой строкой процессу init предписывается выполнить  для инициализации системы. Самой инициализацией занимается	сценарий, так что можно сказать, что init делает не слишком много - он просто делегирует задачу по инициализации системы другому процессу.

Во-вторых, init выполняет все сценарии, на которые есть символьные ссылки из. Это определяется следующей строкой:

И снова все необходимые действия выполняются сценарием rc. Заметьте, что параметр, переданный rc (boot), совпадает с названием используемого подкаталога в.

Теперь init проверяет свой конфигурационный файл, чтобы определить, какой уровень запуска нужно запустить. Для этого из считывается строка:

В приведенном примере (который подходит для подавляющего большинства пользователей Gentoo) номер уровня запуска - 3. Пользуясь этой информацей, init проверяет, что нужно выполнить для запуска уровня запуска 3:

В строке, определяющей уровень 3, для запуска служб снова используется сценарий rc (на этот раз с аргументом default). Опять-таки, обратите внимание, что аргумент, передаваемый сценарию rc, совпадает с названием подкаталога из.

По окончании работы rc, init принимает решение о том, какие виртуальные консоли включить и какие команды выполнить в каждой из них:

Существующие уровни запуска
В предыдущем разделе мы увидели, что init применяет нумерацию для определения уровня запуска, который надо использовать. Уровень запуска - это то состояние, в котором запускается ваша система, он содержит набор сценариев (сценариев уровня запуска или сценариев инициализации), которые следует выполнять, при входе и выходе из определенного уровня запуска.

В Gentoo определено семь уровней запуска: три служебных и четыре определяемых пользователем. Служебные называются sysinit, shutdown и reboot. Действия, совершаемые ими, в точности соответствуют их названиям: инициализация системы, выключение системы и ее перезагрузка.

Определяемые пользователем уровни - это те, которым соответствуют подкаталоги в : boot, default, nonetwork и single. Уровень boot запускает все службы, необходимые системе и используемые всеми остальными уровнями. Остальные уровни отличаются друг от друга запускаемыми службами: default используется для повседневной работы, nonetwork - для тех случаев, когда не требуется сеть, а single используется при необходимости восстановления системы.

Работа со сценариями инициализации
Сценарии, запускаемые процессом rc, называются сценариями инициализации. Каждый сценарий из может запускаться с аргументами start, stop, restart, zap, status, ineed, iuse, needsme, usesme или broken.

Для запуска, остановки или перезапуска службы (и всех, зависящих от нее) следует использовать start, stop и restart:

Если вы хотите остановить службу, но оставить зависимые от нее работающими, можно использовать аргумент  вместе с командой stop:

Чтобы узнать текущее состояние службы (запущена, остановлена, и т.д.), можно использовать аргумент status:

Если указано, что служба работает, но вы знаете, что это не так, можно сбросить состояние на stopped , используя аргумент zap:

Для того, чтобы выяснить зависимости службы, можно использовать аргументы iuse или ineed. С помощью ineed вы увидите те службы, которые действительно необходимы для правильного функционирования интересующей вас службы. С другой стороны, iuse покажет те службы, которые могут использоваться нашей службой, но не обязательны для ее корректной работы.

Аналогично вы можете узнать, какие службы нуждаются в данной службе (needsme) или могут ее использовать (usesme):

Наконец, можно просмотреть список служб, требующихся для данной, но отсутствующих в системе:

rc-update
Система инициализации Gentoo использует дерево зависимостей для определения служб, которые запускаются в первую очередь. Так как это очень утомительное занятие, и мы бы не хотели, чтобы пользователь занимался этим вручную, мы разработали инструменты, упрощающие управление уровнями запуска и сценариями инициализации.

Используя, можно включать и исключать сценарии инициализации из уровней запуска. Из  автоматически запускается сценарий depscan.sh для перестроения дерева зависимостей.

Добавление и удаление служб
В процессе установки Gentoo вы уже добавляли сценарии инициализации в уровень запуска default. Ранее в данном документе было объяснено, что означает default. Кроме уровня запуска, сценарию rc-update требуется второй аргумент, определяющий действие: add (добавить), del (удалить) или show (показать).

Для того, чтобы добавить или удалить сценарий, просто введите  с аргументом add или del, затем название сценария и уровня запуска. Например:

По команде  выводится список всех доступных сценариев с указанием соответствующих уровней запуска:

Вы также можете запустить  (без  ) чтобы просто просмотреть включенные инициализационные скрипты и их уровни запуска.

Почему необходима дополнительная настройка
Сценарии инициализации могут быть весьма сложны. Поэтому нежелательно допускать непосредственное редактирование сценария пользователями, т.к. это может привнести в систему множество ошибок. Но, с другой стороны, необходимо правильно настроить службу. Например, может понадобиться передать службе дополнительные параметры.

Вторая причина, по которой настройки хранятся отдельно от самого сценария - это возможность обновления сценария без опасения, что все ваши настройки будут утеряны.

Каталог conf.d
В Gentoo предусмотрен очень простой способ настройки служб: для каждого сценария, предполагающего настройку, в каталоге есть конфигурационный файл. Например, у сценария, запускающего apache2 (под названием ) есть настроечный файл, где могут храниться нужные вам параметры, передаваемые серверу Apache 2 при запуске:

Такие файлы настроек содержат только переменные (наподобие ), облегчая настройку служб. Это также позволяет нам давать больше информации о переменных (в комментариях).

Это необходимо?
Нет, написание сценариев инициализации обычно не требуется, т.к. Gentoo содержит готовые сценарии для всех поддерживаемых служб. Однако, вы можете установить какую-либо службу, не используя систему Portage; в таком случае, вероятно, вам придется создавать сценарий инициализации самостоятельно.

Не используйте сценарий, идущий со службой, если он не написан специально для Gentoo: сценарии инициализации Gentoo не совместимы со сценариями, используемыми в других дистрибутивах!

Структура
Основная структура сценария инициализации показана ниже.

В любом сценарии должна быть определена функция start. Все остальные разделы необязательны.

Зависимости
Существуют две настройки, работающие с зависимостями, которые вы можете определить, и они будут влиять на порядок запуска инициализационных скриптов: use (использую) и need (нуждаюсь). Кроме этих двух, существуют еще два влияющих на порядок загрузки метода, называющихся before (перед) и after (после). Последние два определяют не зависимости, они не заставят выдать ошибку скрипт, если тот скрипт, что в них описан вообще не должен запуститься (или не запустится).


 * Настройка use информирует систему init, что данный скрипт использует функциональность некоторого скрипта, но строго от него не зависит. Хорошим примером будет use logger или use dns. Если эти сервисы есть, они будут хорошо использоваться, но если у вас нет логгера, или DNS-сервера, сервисы все равно будут работать. Если сервисы существуют, они будут запущены до того, как запустится скрипт, использующий их.
 * Настройка need это жесткая зависимость. Она означает, что скрипт, которому нужен другой скрипт, не запустится, пока другой скрипт не запустится успешно. Также, если другой скрипт будет перезапущен, то этот тоже будет перезапущен.
 * При использовании before, данный скрипт запускается до некоторого скрипта, если выбранный скрипт это часть того же	уровня инициализации. Так, инициализационный скрипт xdm, который определен before alsasound будет запущен до скрипта alsasound, но только если alsasound запланирован запуститься на том же уровне инициализации. Если alsasound не запланирован запуститься, то эта конкретная настройка не будет иметь эффекта, и xdm запустится в тот момент времени, который система init посчитает лучшим вариантом.
 * Похожим образом, after информирует систему init, что данный скрипт нужно запустить после некоторого скрипта, если выбранный скрипт является частью того же уровня инициализации. Если нет, то настройка не имеет эффекта, и скрипт будет запущен системой init в момент времени, который, как она посчитает, будет наилучшим.

Из вышенаписанного должно быть ясно, что need это единственная действительная настройка зависимостей, так как она влияет на то, будет ли запущен скрипт или нет. Все остальные являются больше указателями системе init, говорящими в каком порядке скрипты могут (или должны) запускаться.

Теперь, если вы посмотрите на многие из существующих инициализационных скриптов Gentoo, вы заметите, что некоторые из них имеют зависимости от вещей, которые не являются инициализационными скриптами. Эти вещи мы называем виртуальными.

Виртуальная зависимость - это зависимость от функций, предоставляемых службой, но не какой-то единственной службой. Сценарий может зависеть от службы системного журнала, но таких достаточно много (metalogd, syslog-ng, sysklogd и т.п.). Поскольку нельзя нуждаться в каждой из них (ни в одной вразумительной системе они не запущены все сразу), мы обеспечили предоставление виртуальной зависимости всеми этими службами.

Например, давайте взглянем на информацию о зависимостях postfix.

Как можно увидеть, сервис postfix:
 * требует сеть (net): виртуальная зависимость, удовлетворяемая, например,
 * использует журнал (logger): виртуальная зависимость, удовлетворяемая, например,
 * использует службу имен (dns): виртуальная зависимость, удовлетворяемая, например,
 * предоставляет почтовый агент (mta): виртуальная зависимость, общая для всех программ - почтовых серверов

Порядок запуска
Как мы описали в предыдущем разделе, вы можете сказать системе init, в каком порядке она должна запускать (или останавливать) скрипты. Этот порядок поддерживается как через настройки зависимостей use и need, так и через настройки порядка before и after. Так как мы описали их ранее, давайте посмотрим на сервис Portmap, как на пример такого инициализационного скрипта.

Также можно использовать знак "*", чтобы охватить все службы данного уровня запуска, хотя это не рекомендуется.

Если ваш сервис должен писать на локальные диски, он должен потребовать localmount. Если он что-либо поместит в, например, pid-файл, он должен запускаться после bootmisc:

Стандартные функции
Следом за разделом depend вам потребуется определить функцию start. В ней содержатся все команды, необходимые для запуска вашей службы. Рекомендуется применять функции ebegin и eend для сообщений пользователю о том, что происходит:

Как --exec, так и --pidfile должны использоваться в функциях start и stop. Если сервис не создает pid-файл, тогда используйте --make-pidfile, если возможно, хотя лучше протестировать это, чтобы быть уверенным. Иначе, не используйте pid-файлы. Вы также можете добавить --quiet к опциям start-stop-daemon, но это не рекомендуется, если только сервис не очень многословный. Использование --quiet может скрыть информацию если сервис не сможет запуститься.

Другой интересной настройкой, используемой в вышеприведенном примере является проверка содержимого переменной RC_CMD. В отличие от предыдущей инициализационной системы, новая система openrc не поддерживает отдельную функциональность restart для каждого скрипта. Вместо этого, скрипт должен проверить содержимое переменной RC_CMD, чтобы проверить, вызывается ли функция (как start, так и stop) как часть restart, или нет.

Если вам нужны дополнительные примеры функции start, пожалуйста, прочитайте исходные коды сценариев инициализации, находящихся в каталоге.

Еще одной функцией, которую можно определить (но вы не обязаны это делать), является stop. Система инициализации, применяемая нами, достаточно развита и в состоянии самостоятельно заполнить эту функцию, если вы используете start-stop-daemon.

Если ваш сервис запускает некоторый другой скрипт (например, на bash, python или perl), и этот скрипт позднее изменяет имя (например, с foo.py на foo), тогда вам нужно добавить --name к start-stop-daemon. Вы должны определить имя, на которое имя файла будет изменено. В приведенном примере, сервис запускает foo.py, а потом это имя меняется на foo:

start-stop-daemon has an excellent man page available if more information is needed:

Gentoo's init script syntax is based on the POSIX Shell so people are free to use sh-compatible constructs inside their init scripts. Keep other constructs, like bash-specific ones, out of the init scripts to ensure that the scripts remain functional regardless of the change Gentoo might do on its init system.

Adding custom options
If the initscript needs to support more options than the ones we have already encountered, then add the option to the extra_commands variable, and create a function with the same name as the option. For instance, to support an option called restartdelay:

Service configuration variables
In order to support configuration files in, no specifics need to be impleneted: when the init script is executed, the following files are automatically sourced (i.e. the variables are available to use):

Also, if the init script provides a virtual dependency (such as net), the file associated with that dependency (such as ) will be sourced too.

Who might benefit from this
Many laptop users know the situation: at home they need to start net.eth0, but they don't want to start net.eth0 while on the road (as there is no network available). With Gentoo ythe runlevel behaviour can be altered at will.

For instance, a second "default" runlevel can be created which can be booted that has other init scripts assigned to it. At boottime, the user can then select what default runlevel to use.

Using softlevel
First of all, create the runlevel directory for the second "default" runlevel. As an example we create the offline runlevel:

Add the necessary init scripts to the newly created runlevel. For instance, to have an exact copy of the current default runlevel but without net.eth0:

Even though net.eth0 has been removed from the offline runlevel, udev might want to attempt to start any devices it detects and launch the appropriate services, a functionality that is called hotplugging. By default, Gentoo does not enable hotplugging.

To enable hotplugging, but only for a selected set of scripts, use the  variable in :

Edit the bootloader configuration and add a new entry for the offline runlevel. In that entry, add  as a boot parameter.

Using bootlevel
Using bootlevel is completely analogous to softlevel. The only difference here is that a second "boot" runlevel is defined instead of a second "default" runlevel.