С запуска init
начинается загрузка самой системы. В давние времена, во времена молодости Linux и ранее, в этом месте никаких подводных камней не наблюдалось. Если ядро содержало подпрограммы для работы со всеми необходимыми устройствами (т. н. «драйверы»), оно загружалось и запускало init
. Если ядру недоставало каких-то важных драйверов (например, поддержки дискового массива, с которого и шла загрузка) — не загружалось и не запускало. Из положения выходили просто: в ядро старались включить как можно больше драйверов. Такое ядро называлось базовым (generic), и имело довольно внушительный размер. Загрузивши систему с базовым ядром, администратор обычно пересобирал его: выбрасывал из специального файла-профиля драйверы всех отстутствующих в системе устройств, быть может, добавлял новые (те, что не нужны для загрузки, но нужны для работы, например, звуковые), и компилировал из исходных текстов новое, профильное ядро.
Стартовый виртуальный диск и модули ядра
Пересборка ядра нынче требуется очень редко. Во-первых, в Linux поддерживается несметное число различных внешних устройств, драйверы которых (особенно похожих, но разных) вполне могут помешать друг другу работать, если их использовать одновременно. Пришлось бы собирать множество разных ядер, без возможности указать пользователю, какое из них годится. Во-вторых, выяснением того, какой именно драйвер необходим найденному устройству, занимаются сейчас специальные программы, в распоряжении которых есть целые базы данных — ядру такую работу делать неудобно, да и незачем. Это делает процедуру пересборки ядра почти что обязательной (пока не загруженио базовое ядро, непонятно, какие драйверы добавлять в профильное). А в-третьих, пресборка ядра требует весьма высокой квалификации того, кто его пересобирает. Этот процесс нельзя ни автоматизировать, ни упростить. Утилита linuxconf
, устроенная именно для этого на основе окон и меню, даёт на выходе работоспособное ядро в трёх случаях: (1) в руках профессионала, (2) при чётком следовании полной инструкции и (3) по случайности.
Не надо вручную пересобирать ядро, даже если учебник по Linux это советует!
Совсем другие времена настали, когда изобрели и активно внедрили в Linux загружаемые модули ядра. Модуль ядра — это часть ядра Linux, которую можно добавлять и удалять во время работы системы. Модуль ядра — не процесс, он работает в режиме супервизора и в таблице процессов не регистрируется: это набор подпрограмм для работы с определённым устройством, которые добавляются к возможностям ядра.
Этим он скорее похож на динамическую библиотеку.
При загрузке в память модуль компонуется с ядром, образуя с ним одно целое. Просмотреть список загруженных модулей можно командой lsmod
, а подгрузить модуль в память, добавив его к ядру, и удалить его оттуда — командами insmod
и rmmod
соответственно.
# lsmod
Module Size Used by Not tainted
usb-uhci 21676 0 (unused)
usbcore 58464 1 [usb-uhci]
af_packet 12392 1 (autoclean)
pcnet32 15140 1 (autoclean)
mii 2544 0 (autoclean) [pcnet32]
crc32 2880 0 (autoclean) [pcnet32]
floppy 48568 0 (autoclean)
subfs 4296 4 (autoclean)
ac 1792 0
rtc 6236 0 (autoclean)
ext3 62288 2
jbd 37852 2 [ext3]
Пример 4. Получение списка загруженных модулей
Изменилось и базовое ядро: теперь оно включает в себя только устройства, необходимые для загрузки системы: главным образом диски и графическую консоль. Остальные устройства определятся уже самой системой, тогда можно будет и распознать экзотическую аппаратуру, и модуль для неё подгрузить. Однако полностью перевести драйверы всех внешних устройств в модули мешает вот какое соображение: что, если загрузка системы происходит именно с того устройства, чей модуль ещё не загружен в ядро, например, с дискового массива (RAID). Вторичный загрузчик и ядро можно, недолго думая, разместить на другом носителе (например, на лазерном диске) или добыть с дискового массива средствами BIOS (карты размещения позволяют не обращать внимания на логическую структуру RAID). Но как добыть модуль работы с RAID, тот самый, что распознает эту логическую структуру?
- модуль ядра
- Необязательная часть ядра, расширяющая его функциональность. Модуль можно загрузить в память или удалить оттуда в процессе работы системы.
Подсистема загрузки GRUB
умеет разбираться в файловых системах и даже подключать модули к ядру, однако для того, чтобы сделать процесс загрузки более или менее универсальным, пришлось бы обучить GRUB всем видам логики RAID, и всем способам подключения модулей. И то, и другое постоянно изменяется, и успевать за этими изменениями означает поддерживать собственную, параллельную Linux, дисковую подсистему.
Вдумаемся. Для того, чтобы средствами Linux подключить модуль ядра, работающий с дисковым устройством, необходимо загрузить Linux с этого же устройства. Так ли это невозможно? Ведь если можно прочесть оттуда «ядро», то, наверное, можно прочесть и «Linux»? Более точно, вдобавок к одной области данных, соответствущей ядру, надо прочитать вторую, соответствующую некоторой уменьшенной до предела установке Linux, в которой содержатся только нужные программы и модули, загрузить оттуда «маленький Linux», который настроит и подключит злополучный RAID и запустит процесс загрузки полноценной системы оттуда.
Предельно сжатый вариант Linux есть, это проект busybox
, используемый во встроенных системах, где дорог каждый байт. Разместить файловую систему в памяти тоже легко, этим, например, занимается модуль tmpfs
, который можно включить в базовое ядро (подробнее о типах файловых систем рассказано в лекции Работа с внешними устройствами). Осталось только обучить подсистемы загрузки GRUB
и LILO
считывать не одну, а две области данных — ядро и образ файловой системы. Ядру при этом передаётся параметр «пользуйся виртуальным диском», чтобы оно подключило загруженный образ в качестве временной корневой файловой системы. Можно также потребовать, чтобы память, занимаемая временной файловой системой, освобождалась в процессе дальнейшей загрузки.
Такой механизм называется initrd
(initial ram ddisk, где «ram» — это не «баран», а random access memory, то есть оперативная память) или стартовым виртуальным диском. Стартовый виртуальный диск собирается по команде mkinitrd
в соответствии с профилем компьютера, и записывается на диск по тем же правилам, что и ядро. В примере двухсистемной машины, за которой работал Мефодий, также был стартовый виртуальный диск, причём довольно маленький:
[root@localhost root]# ls -lg /boot
drwxr-xr-x 2 root 4096 Nov 20 21:08 grub
-rw------- 1 root 205374 Nov 9 01:33 initrd-2.4.26-std-up.img
lrwxrwxrwx 1 root 29 Nov 9 01:33 initrd-up.img -> initrd-2.4.26-std-up.img
-rw------- 1 root 45056 Nov 20 19:07 map
-rw-r--r-- 1 root 935892 Aug 3 21:59 vmlinuz-2.4.26-std-up
lrwxrwxrwx 1 root 26 Nov 9 01:33 vmlinuz-up -> vmlinuz-2.4.26-std-up
Пример 5. Размеры и наименование файлов с ядром и стартовым виртуальным диском
Как видно из примера, ядро в четыре раза превосходит размером стартовый виртуальный диск. Стоит заметить, что и ядро, и образ диска упакованы с помощью утилиты gzip
(причём ядро умеет распаковываться в памяти самостоятельно), поэтому их действительный размер больше. В файле map
хранится карта размещения LILO
, а упомянутые в lilo.conf
и menu.lst
файлы vmlinuz-up
и initrd-up.img
оказались символьными ссылками на файлы с более говорящими именами. Никаких требований к названиям ядер в Linux нет, это дело авторов дистрибутива. В этом случае в имени ядра и образа диска встречается версия ядра (2.4.26
), тип сборки std
(по-видимому, «standard») и тип архитектуры up
(uniprocessor, т. е. однопроцессорная).
- стартовый виртуальный диск
- Минимальный набор программ и модулей Linux, необходимый для обеспечения загрузки системы. Представляет собой виртуальную файловую систему в оперативной памяти. Загружается вторичным загрузчиком вместе с ядром.
Отец всех процессов
Если в параметрах не сказано иного, ядро считает, что init
называется /sbin/init
. В стартовом виртуальном диске это обычно некоторый простейший сценарий, а в полноценной системе у init
другая задача: он запускает все процессы. Если не он сам, то его потомки, так что все процессы Linux, кроме ядерных, происходят от init
, как весь род людской — от Адама.
Первым делом init
разбирает собственный конфигурационный файл — /etc/inittab
. Файл этот имеет довольно простую структуру: каждая строка (если она не комментарий) имеет вид «id: уровни: действие: процесс
», где id
— это некоторая двух- или однобуквенная метка, уровни
— это слово, каждая буква которого соответствует уровню выполнения, (об уровнях выполнения будет рассказано далее), действие
— это способ запуска процесса
. Например, запись 4:2345:respawn:/sbin/mingetty tty4
означает, что меткой «4
» помечен запуск /sbin/mingetty tty4
на уровнях выполнения 2
, 3
, 4
и 5
по алгоритму «respawn» (запустить в фоне, а когда процесс завершится, запустить заново).
mingetty
— упрощённый аналог getty
, работающий только на виртуальных консолях.
Помимо «respawn» существуют методы «once» (запустить в фоне однократно), «wait» (запустить интерактивно, при этом никаких других действий не выполняется, пока процесс не завершится) и множество других, включая даже «ctrlaltdel» — процесс, запускаемый, когда пользователь нажимает на консоли Ctrl+Alt+Del
.
Понятно, что Ctrl+Alt+Del
— это не reset
, а обычное сочетание клавиш. Для удобства пользователя его специально распознаёт клавиатурный драйвер, а ядро сообщает об этом init
-у.
Наконец-то Мефодий до конца понял, отчего getty
ведёт себя так непохоже на остальные процессы: не просто запускает из-под себя login
, а дожидается окончания его работы, отсутствуя при этом в таблице процессов. На самом деле дожидается не getty
, а init
, используя метод «respawn»: порождается (в фоне) процесс getty
с определённым PID, а init
бездействует до тех пор, пока существует процесс с этим PID getty
, login
, стартовый командный интерпретатор или программа, запущенная из него с помощью exec
); когда же процесс, наконец, умирает, порождается новый getty
.
Запуск системных служб
Полноценно загруженная Linux-система — не только login
на виртуальной консоли. Системе есть чем заняться и помимо идентификации пользователей. Даже если компьютер не работает WWW-, FTP- или почтовым сервером для «внешнего мира», себе самой и своим пользователям система предоставляет множество услуг: отсылка заданий на печать и обеспечения их очереди, запуск заданий по расписанию, проверка целостности и т. п. Набор утилит и системных программ, предназначенных для предоставления таких услуг, принято называть подсистемами или службами.
Чему служат демоны?
Как правило, системная служба организована так. Во время начальной загрузки запускается в фоновом режиме программа, которая всё время работы системы находится в таблице процессов, однако большей частью бездействует, ожидая, когда её о чем-нибудь попросят. Для того, чтобы попросить эту программу об услуге, которую она предоставляет, используются утилиты, взаимодействующие с ней по специальному протоколу. По аналогии с сократовским «даймонионом», который незримо присутствует, по своей инициативе не делает ничего, не даёт совершать плохое и потворствует хорошему, такую программу стали называть «daemon». Не знакомые с творчеством Платона программисты-любители частенько переименовывали её в «demon» (демон); к сожалению, именно в такой, слегка инфернальной форме, daemon и вошёл в русскоязычную терминологию. Выходит, что в Linux услуги пользователям предоставляют... демоны!
- демон
- Запускаемая в фоне программа, длительное время пребывающая в таблице процессов. Обычно демон активизируется по запросу пользовательской программы, по сетевому запросу или по наступлению какого-либо системного события.
В ранних версиях UNIX всё, что нужно было запускать при старте системы, вписывалось в inittab
. Было довольно удобно в одном файле указывать, какие именно демоны должны работать в системе, и в каком порядке их запускать. Само поведение демона при запуске явно рассчитано на использование в inittab
по методу «wait»: классический демон запускается интерактивно, проверяя правильность конфигурационных файлов и прочие условия работы, а затем самостоятельно уходит в фон (попросту делая fork()
и завершая родительский процесс). Таким образом, init
ждёт, пока демон работает интерактивно, а когда служба, возглавляемая этим демоном, готова к работе, переходит к следующей строке inittab
. Однако часто бывает так, что автор демона знать не знает, какие именно условия разработчики той или иной версии Linux сочтут пригодными для запуска. Для этого ими создаётся стартовый сценарий, в котором запрограммирована логика запуска и останова службы. Кроме того, если на каждом из уровней выполения запускается много различных служб, попытка записывать их запуск в inittab
делает его громоздким и совсем неочевидным.
Гуревич посоветовал Мефодию отложить на время изучение загрузки системы, а сначала посмотреть, как управлять стартовыми сценариями.
Стартовый сценарий системной службы
Стартовый сценарий — программа (обычно написанная на shell), управляющая включением или выключением какого-нибудь свойства системы. Это может быть запуск и остановка HTTP-сервера, активизация и деактивизация сетевых настроек, загрузки модулей и настройка звуковой подсистемы и т. п. Простейший стартовый сценарий обязан принимать один параметр, значение которого может быть словом «start» для запуска (включения) и «stop» для остановки (выключения). Если в определённом дистрибутиве Linux принято решение, что стартовые сценарии должны понимать и другие параметры, например «restart» (обычно «stop» + «start», но не всегда) и «status» (для опроса состояния), это требование распространяется на все стартовые сценарии. Единообразие позволяет, например, легко запускать и останавливать демоны, не выясняя, каков PID останавливаемого процесса и какой именно сигнал ему следует послать. Достаточно запуск написать так, чтобы PID процесса откладывался в специальный файл (обычно /var/run/имя_службы
), а в остановку вписать что-то вроде kill -правильный_сигнал `cat /var/run/имя_службы`
.
Все стартовые сценарии служб, которыми может воспользоваться система, принято хранить в каталоге /etc/rc.d/init.d
(в некоторых дистрибутивах, для совместимости со старыми версиями UNIX, используется /etc/init.d
, иногда это — просто символьная ссылка на /etc/rc.d/init.d
). Запустить или остановить службу можно, просто вызвав соответствующий сценарий с параметром «start» или «stop». Часто ту же самую задачу выполняет и специальная команда service
— которая проверяет, есть ли указанный стартовый сценарий, и запускает его.
В некоторых дистрибутивах Linux такая команда может называться invoke-rc.d
, а команда, аналогичная описанному ниже chkconfig
— update-rc.d
.
[root@localhost root]# lsmod > old
[root@localhost root]# /etc/rc.d/init.d/sound stop
Saving OSS mixer settings: [ DONE ]
Unloading sound module (es1371): [ DONE ]
[root@localhost root]# lsmod > nosound
[root@localhost root]# service sound start
Loading sound module (es1371): [ DONE ]
Loading OSS mixer settings: [ DONE ]
[root@localhost root]# lsmod > new
[root@localhost root]# diff3 old new nosound
====3
1:2,5c
2:2,5c
es1371 25608 0
ac97_codec 11880 0 [es1371]
soundcore 3652 4 [es1371]
gameport 1628 0 [es1371]
3:1a
Пример 6. Перезапуск звуковой подсистемы
Здесь Мефодий сначала остановил, а потом снова активизировал звуковую подсистему. Остановка привела к выгрузке звуковых модулей, а повторный запуск — к загрузке, полностью аналогичной исходной. В этом Мефодий убедился, сравнив с помощью утилиты diff3
три списка модулей: old
(до остановки звуковой подсистемы), new
(после повторного запуска) и nosound
(между остановкой и повторным запуском). Файлы old
и new
полностью одинаковы, а от nosound
оба отличаются тем, что со второй строки по пятую содержат названия тех самых модулей ядра (среди которых затесался gameport
, отвечающий за джойстик).
Схема «. d»
Итак, имеется способ единообразно и гибко управлять запуском и остановкой каждой системной службы в отдельности (или включением и выключением одного свойства системы). Однако задача целиком огранизовать загрузку системы, от запуска init
до полноценной работы, этим ещё не решается. Первая из возникающих задач такова: чаще всего нужно загружать не все из размещённых в /etc/rc.d/init.d
сценариев, потому что некоторые из установленных в системе служб администратор решил не использовать. Удалять оттуда не используемые при загрузке сценарии — значит, лишать администратора возможности запускать эти сценарии вручную.
Создателям ранних версий UNIX пришла в голову простая мысль: написать один большой сценарий по имени /etc/rc
, в который и заносить только нужные для запуска команды вида /etc/init.d/сценарий start
. Можно даже занести туда все имеющиеся стартовые сценарии, но строки, запускающие те, что не используются, закомментировать. Такая (монолитная) схема имела существенный недостаток: добавление и удаление службы в систему (например, добавление и удаление пакета, содержащего исполняемые файлы службы) требовало редактирования этого файла. Если учесть, что порядок запуска служб весьма важен (например, бессмысленно запускать сетевые демоны до активизации сетевых настроек), становится ясно, что автоматическое изменение такого файла не может гарантировать нормальную загрузку системы, а значит, недопустимо.
На помощь пришла тактика, известная под именем «схема. d». Суть её в следующем. Пусть некоторый процесс управляется конфигурационным файлом, содержимое которого зависит от наличия и активации других служб системы (таким процессом может быть демон централизованной журнализации syslogd
, ведущий журнал всех событий системы, или сетевой метадемон inetd
, принимающий сетевые запросы и превращающий сетевой поток данных в обыкновенный посимвольный ввод-вывод). Тогда, чтобы избежать постоянного редактирования конфигурационного файла, его превращают в каталог (например, вдобавок к файлу /etc/syslog.conf
заводится каталог /etc/syslog.d
). Каждый файл в таком каталоге соответствует настройке одной службы: при добавлении её в систему файл появляется, при удалении — исчезает. Остаётся только обучить тот же syslog
читать настройки не из одного syslog.conf
, но и из всех файлов в syslog.d
, и задача решена.
На случай запускаемых сценариев схема «. d» распространяется с двумя дополнениями. Во-первых, как уже было сказано, стартовые сценарии можно запускать, а можно и не запускать. Поэтому сам init.d
не годится на роль «. d»-каталога. Впрочем, достаточно организовать ещё один каталог, скажем, rc.d
, и создать там ссылки (для наглядности лучше символьные) на те сценарии из init.d
, которые планируется запускать при старте системы. Общий стартовый сценарий rc
как раз и будет заниматься запуском стартовых сценариев из rc.d
.
Во-вторых, необходимо обеспечить строгий порядок запуска этих сценариев. Теоретически это совсем просто: отсортировать их по алфавиту, как это делает ls
и запускать подряд. Практически же такое требование накладывает ограничение на имя ссылки в «. d»-каталоге, поэтому принято, чтобы в начале имени стояло двузначное число. Тогда, запуская подряд все сценарии, отсортированные алфавитно, rc
будет в первую очередь руководствоваться этим номером, а уж потом — названием службы, которое после него стоит.
Уровни выполнения
В Linux схема начальной загрузки слегка сложнее, чем обычная «. d». Связано это с тем, что одну и ту же систему в разных случаях бывает необходимо загружать с разным набором служб. Если, скажем, использование сети нежелательно, удобнее сказать что-то вреде «Система! Загружайся без сети!», чем вручную удалять стартовые сценарии всех предположительно сетевых служб их «. d»-каталога. Необходимость выбора возникает также, если компьютер используется в качестве рабочей станции с запуском графической среды и всего с нею связанного или в качестве стоечного сервера, управлять которым лучше с системной консоли.
Поэтому в Linux предустотрено несколько вариантов начальной загрузки, называемых уровни выполнения (run levels). Уровни выполнения нумеруются с 0
до 9
:
- Уровень
1
соответствует однопользовательскому режиму загрузки системы. При загрузке на уровень1
не запускается никаких служб, и даже системная консоль, как правило, бывает доступна только одна, так что в системе может работать не более одного пользователя. В однопользовательском режиме изредка работает администратор — исправляет неполадки системы, изменяет ключевые настройки, обслуживает файловые системы. - Уровень
2
соответствует многопользовательскому режиму загрузки системы с отключённой сетью. В этом режиме не запускаются никакие сетевые службы, что, с одной стороны, соответствует строгим требованиям безопасности, а с другой стороны, позволяет запускать службы и настраивать сеть вручную. - Уровень
3
соответствует многопользовательскому сетевому режиму загрузки системы. Сеть при загрузке на этот уровень настроена, и все необходимые сетевые службы запущены. На этом уровне обычно работают компьютеры-серверы. - Уровень
5
соответствует многопользовательскому графическому режиму загрузки системы. На этом уровне обычно работают рабочие станции, предоставляя пользователям возможность работать с графической подсистемойX11
. Сеть на этом уровне настроена, а вот список запущенных сетевых служб может быть меньше, так как рабочая станция не всегда выполняет серверные функции (хотя, безусловно, может). - Уровни
0
и6
— специальные. Они соответствуют останову и перезагрузке системы. В сущности, это удобные упрощения для действий, обратных загрузке на уровень: все службы останавливаются, диски размонтируются. В случае останова даже электропитание можно отключать программно, если аппаратура позволяет, а в случае перезагрузки система идёт на повторную загрузку.
Остальные уровни никак специально в Linux не описаны, однако администратор может использовать и их, определяя особый профиль работы системы. Переход с уровня на уровень происходит очень просто: по команде init номер_уровня
. На какой уровень загружаться при старте ситемы, написано в inittab
(в поле действие должно быть написано «initdefault», а в поле уровни
— только одна цифра). Узнать текущий уровень выполнения можно с помощью команды runlevel
:
[root@localhost root]# grep initdefault /etc/inittab
id:3:initdefault:
[root@localhost root]# runlevel
N 3
Пример 7. Задание и просмотр уровня выполнения
- уровень выполнения
- Сохранённый профиль загрузки системы. В Linux реализован выполнением всех сценариев остановки и запуска служб из подкаталога
rc.уровеньd
каталога/etc
или/etc/rc.d
Схема «. d» легко учитывает уровни выполнения. В каталоге /etc/rc.d
заводится несколько «. d»-подкаталогов, соответствующих каждому уровню выполнения: /etc/rc.d/rcуровень.d
.
В некоторых дистрибутивах — в каталоге /etc/
Именно оттуда их запускает стартовый сценарий /etc/rc.d/rc
.
[root@localhost root]# ls -F /etc/rc.d
init.d/ rc.powerfail* rc0.d/ rc2.d/ rc4.d/ rc6.d/
rc* rc.sysinit* rc1.d/ rc3.d/ rc5.d/ scripts/
[root@localhost root]# ls /etc/rc2.d
K10power K75netfs S15random S31klogd S37gpm S54sshd
K44rawdevices K95kudzu S30sound S32hotplug S40crond S98splash
K50xinetd S10network S30syslogd S35keytable S41anacron S99local
[root@localhost root]# ls -l /etc/rc2.d/ K75netfs
lrwxrwxrwx 1 root root 15 Nov 9 01:16 /etc/rc2.d/K75netfs -> ../init.d/netfs
Пример 8. Содержимое каталогов /etc/rc.d
и /etc/rc.d/rc2.d
Переход с уровня на уровень должен сопровождаться не только запуском, но и остановкой служб. Это касается не только уровней 0
и 6
, но и любых других. Например, при переходе с уровня 3
на уровень 2
необходимо остановить все сетевые службы. Поэтому схема «. d» была расширена: сначала с параметром «stop» запускаются сценарии, имена которых начинаются на «K» (Kill), а затем, с параметром «start» — те, имена которых начинаются на «S» (Start). В приведенном примере при переходе на уровень 2
останавливаются несколько служб, в том числе сетевой метадемон (K50xinetd
) и монтирование по сети удалённых файловых систем (K75netfs
). Если при переходе с уровня на уровень некой службе не требуется менять своего состояния, сценарий не запускается вовсе. Так, при переходе с уровня 3
на уровень 2
сетевые настройки остаются активными, поэтому соответствующий сценарий (S10network
), скорее всего, запущен не будет.
Долгое время считалось, что определение порядка загрузки — дело системного администратора, поэтому расставлять символьные ссылки в каталоги rc*.d
приходилось вручную. Однако одно из другого не следует: можно предусмотреть и более лёгкий способ наполнения этих каталогов ссылками. Один из способов такой: поставить в стартовый сценарий комментарий особого вида, в котором и описать, на каких уровнях служба должна быть активизирована, и какой по порядку должна быть запущена и остановлена:
[root@localhost root]# grep chkconfig /etc/init.d/netfs
# chkconfig: 345 25 75
[root@localhost root]# chkconfig --list netfs
netfs 0:off 1:off 2:off 3:on 4:on 5:on 6:off
[root@localhost root]# ls /etc/rc.d/rc*.d/*netfs
/etc/rc.d/rc0.d/K75netfs /etc/rc.d/rc3.d/S25netfs /etc/rc.d/rc6.d/K75netfs
/etc/rc.d/rc1.d/K75netfs /etc/rc.d/rc4.d/S25netfs
/etc/rc.d/rc2.d/K75netfs /etc/rc.d/rc5.d/S25netfs
Пример 9. Управление порядком выполнения стартовых сценариев
Здесь Мефодий использовал утилиту chkconfig
, которая ищет в стартовом сценарии комментарий вида chkconfig: уровни вкл выкл
, и самостоятельно проставляет ссылки в соответствии с этими полями: во всех каталогах, упомянутых в уровнях
соответствующий netfs
сценарий имеет вид Sвклnetfs
, а во всех остальных — Kвыклnetfs
. Эта же утилита позволяет добавлять и удалять службу на каждом уровне в отдельности или запрещать её вовсе.
Загрузка типичной системы на уровень выполнения 5
Итак, что же происходит после запуска init
?
[root@localhost root]# grep rc /etc/inittab
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
[root@localhost root]# grep initdefault /etc/inittab
id:5:initdefault:
Пример 10
. Стартовые сценарии в /etc/inittab
Метод «sysinit» в inittab
означает, что процесс запускается во время начальной загрузки системы, до перехода на какой-нибудь уровень выполнения. Следовательно, первым запускается сценарий /etc/rc.d/rc.sysinit
. Он настраивает аппаратуру дисковых массивов, проверяет и монтирует дисковые файловые системы, инициализирует область подкачки, межсетевой экран — словом, делает всё, без чего дальнейшая полноценная загрузка системы невозможна. Далее из строчки с «initdefault» init
узнаёт, что уровень выполнения по умолчанию — пятый (многопользовательский графический), и выполняет все строки из inittab
, в поле уровни
которых есть 5
. В частности, запускается сценарий rc
с параметром 5
(l5:5:wait:/etc/rc.d/rc 5
), который и выполняет необходимые действия из «. d»-каталога /etc/rc.d/rc5.d
. Метод запуска rc
— «wait», так что init
ждёт, пока не выполнятся все стартовые сценарии, а потом продолжает разбор inittab
.
[root@localhost root]# ls /etc/rc.d/rc5.d/
K10acpid S10network S30syslogd S37gpm S50xinetd
K20nfs S13portmap S31klogd S40crond S54sshd
K65apmd S15random S32hotplug S41anacron S56rawdevices
K86nfslock S25netfs S35keytable S44xfs S64power
S05kudzu S30sound S36update_wms S45dm S98splash
Пример 11. Профиль системы на уровне выполнения 5
Мефодий заметил, сценарий K20nfs
(с параметром «stop») не выполнился: соответствующего сообщения на системной консоли не появилось. Беглый просмотр /etc/rc.d/init.d/nfs
показал, что этот сценарий предназначен для запуска и остановки сервера сетевой файловой системы (NFS). Сервер используется на уровне 3
, а на уровне 5
— нет, поэтому при переходе с 3
на 5
его следует останавливать. Поскольку во время начальной загузки останавливать нечего, сценарий не выполнился.
Из служб, запускаемых именно на пятом уровне, примечателен шрифтовый сервер, под номером 44
, (the Xfont server, xfs
) — программа, у которой графическая подсистема получает шрифты (нередко по сети, тогда такой сервер может быть один на несколько рабочих станций), и экранный диспетчер, под номером 45
, (the Xdisplay manager, xdm
) — программа, регистрирующая пользователя на манер login
, с той разницей, что регистрация и запуск графических приложений могут происходить по сети с удалённого компьютера.
Не путать с диспетчером окон, описанным в лекции Графический интерфейс (X11).
Тут разрешилась ещё одна загадка: вместо обычной виртуальной консоли и login
-а, Мефодий нередко наблюдал окно графической подсистемы с надписью «Login:» и «Password:», а кое-где даже «Логин:», «Пароль:» и портрет самого пользователя! Оказывается, это были различные версии xdm
. Дабы не забивать себе голову разрозненными сведениями, Мефодий решил до поры (до лекции Графический интерфейс (X11)) не использовать графическую среду и нажал Ctrl+Alt+F1
, переключившись в текстовую консоль.
Текстовая консоль на пятом уровне доступна: записи вида 1:2345:respawn:/sbin/mingetty tty1
обычно включают 5
в поле уровни
.