...
...

Процесс INIT

Окончание, начало в N№ 49
Давайте посмотрим, как полный /etc/inittab может заботиться обо всем, что необходимо для нормальной работы системы, включая различные уровни запуска. Хотя все карты раскрыты в файле /etc/inittab, нужно выполнить еще некоторые действия по конфигурации системы (простейший inittab приведен выше). Я считаю необходимым описать два способа конфигурации, первый я называю "путь Slackware", а второй — "путь Debian" по именам известных дистрибутивов Linux, которые используют эти способы.

Как это делает Slackware
Хотя прошло уже достаточно много времени после того, как я в последний раз устанавливал Slackware, документация, включенная в SysVinit-2.74, говорит, что все работает по тем же законам. У него меньше возможностей, но работает он быстрее, чем у Debian. Мой 486-й компьютер использует вариант /etc/inittab от Slackware только для выигрыша в скорости.

Листинг 3. Inittab дистрибутива Slackware
# уровень запуска по умолчанию
id:5:initdefault
# инициализация системы (выполняется при загрузке)
si:S:sysinit:/etc/rc.d/rc.S
# Скрипт, выполняемый в однопользовательском режиме
# (уровень запуска 1)
su:1S:wait:/etc/rc.d/rc.K
# Скрипт, выполняемый в многользовательском режиме
rc:2345:wait:/etc/rc.d/rc.M
# Что делать, когда нажаты CTRL-ALT-DEL
ca::ctrlaltdel:/sbin/shutdown -t5 -rf now
# (уровень запуска 0) — останов системы
l0:0:wait:/etc/rc.d/rc.0
# (уровень запуска 6) — перезагрузка системы
l6:6:wait:/etc/rc.d/rc.6
# (уровень запуска 1,2,3,5) — обработка внешних подключений
c1:1235:respawn:/sbin/agetty 38400 tty1 linux
# (уровень запуска 4) — графический оконный интерфейс
x1:4:wait:/etc/rc.d/rc.4
# запуск getty на /dev/tty4 только в случае...
c4:4:respawn:/sbin/agetty 38400 tty1 linux

Фрагмент файла /etc/inittab, используемого в системах Slackware, приведен в Листинге 3. Обратите внимание, что уровни запуска 0, 1 и 6 имеют особое значение. Это хорошо видно в командах инициализации, а еще лучше в части листинга, которая описывает отключение системы. Если Вы хотите остановить либо перезагрузить компьютер, Init получает указание перейти на 0 или 6 уровень запуска, после вызова /etc/rc.d/rc.0 или /etc/rc.d/rc.6 соответственно.
Это работает надежно, потому что когда init переходит на другой уровень запуска, он прекращает запускать задачи, не описанные в настройках данного уровня запуска, а каждая активная копия задачи прекращает свою работу. В этом случае активной задачей является /sbin/agetty.

Конфигурация Init в этом случае достаточно проста, как и роль каждого файла:
— /etc/rc.d/rc.S выполняется при загрузке системы, независимо от уровня запуска. В этот файл можно добавлять вызов задач, которые должны выполняться при старте системы.
— /etc/rc.d/rc.М выполняется после завершения работы файла rc.S, если система переходит на 2, 3, 4 или 5 уровень запуска. Если Вы загружаете 1-й уровень запуска (однопользовательский режим), этот скрипт не выполняется. Этот файл вызывает все программы, необходимые для работы в многопользовательском режиме.
— /etc/rc.d/rc.К занимается прекращением работы процессов при переходе от многопользовательского к однопользовательскому режиму работы. Если вызов задачи добавляется в файл rc.М, команда останова этой задачи должна быть добавлена в файл rc.К.
— /etc/rc.d/rc.0 и /etc/rc.d/rc.6 отключают и перезагружают компьютер соответственно.
— /etc/rc.d/rc.4 выполняется только при переходе на 4-й уровень запуска. Этот файл запускает процесс "xdm", графический оконный интерфейс. Заметьте, что программа getty не запущена на устройстве /dev/tty1 для этого уровня запуска (если хотите, это можно изменить).
Этот способ настроек прост и понятен, и Вы можете устанавливать различия между вторым, третьим и пятым уровнем запуска при помощи добавления команд wait (выполнить один раз и ждать завершения) и respawn (перезапускать всегда).
Кстати, если Вы еще не знаете, что означают буквы "rc", могу пояснить, что это просто сокращение "run command" — выполнить команду. Можно долгое время корректировать файлы . cshrc или . twmrc, но не знать, что же все-таки обозначает этот суффикс "rc" в названиях некоторых файлов.

Как это делает Debian
Способ настройки файла /etc/inittab, используемый в Slackware, весьма прост, но обратная сторона этой простоты появляется при попытке установить на компьютер новое серверное программное обеспечение или новые модули. Давайте представим, для примера, что кто-то распространяет пакет ssh как дополнительный модуль к Slackware (не из-за того, что ssh не может распространяться официально на дискетах согласно американским законам, касающихся криптографии). Программа sshd — это отдельный сервер, который должен вызываться при загрузке системы, это означает, что при его установке необходимо внести изменения в файл /etc/rc.d/rc.M или в один из скриптов, вызываемых из этого файла, чтобы добавить поддержку ssh. Это является серьезной проблемой в мире, где дистрибутивы представляют собой просто архивы файлов. К тому же, Вы можете и не догадываться, что файл rc.local остался без изменений после установки всех новых пакетов программ и что программа, которая должна внести изменения в этот файл, не сможет этого сделать. Вы должны также учитывать, что добавление новых серверных программ — это только часть работы. Сервер должен быть остановлен при переходе на уровень запуска rc.K, rc.0 и rc.6. А чтобы все это учесть, придется хорошенько поработать.
Оказывается, эта проблема имеет ясное и оригинальное решение. Главная идея состоит в том, что каждый сервер, добавляемый в систему, должен сам добавить два файла-скрипта, один из которых запускает этот сервер, второй останавливает его, тогда каждый уровень запуска будет стартовать и останавливать службы и сервисы, с которыми он связан. Связать конкретный сервис с конкретным уровнем запуска можно легко, создав соответствующие файлы в специальном каталоге, соответствующем этому уровню запуска. Этот способ настройки init используется Debian и Red Hat, и, возможно, другими дистрибутивами, с которыми я не работал.

Листинг 4. Inittab дистрибутива Debian
# уровень запуска по умолчанию
id:2:initdefault;
# Вначале запускается это...
si::sysinit:/etc/init.d/boot
# Что делать в однопользовательском режиме?
~~:S:wait:/sbin/sulogin
# Уровни запуска
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5
l6:6:wait:/etc/init.d/rc 6
# getty
1:2345:respawn:/sbin/getty 38400 tty1

Фрагмент файла /etc/inittab, используемого в Debian 1.3, приведен в Листинге 4. Структура настройки Red Hat в точности соответствует этой схеме, только использует другие имена файлов и каталогов. Вы сможете перенести эту структуру с одной системы на другую. Перечислим роли различных файлов:
— /etc/init.d/boot — полный аналог файла rc.S, обычно он проверяет локальные файловые системы и монтирует их, а также выполняет много других важных функций,
%-2— /sbin/sulogin — дает возможность пользователю root войти в систему в однопользовательском режиме. Показан в Листинге 4 только потому, что однопользовательский режим очень важен для эксплуатации системы,
— /etc/init.d/rc — это скрипт, который и выполняет другие скрипты, запускающие и останавливающие программы, принадлежащие конкретным уровням запуска.
Последний файл — программа rc, главный персонаж в этой пьесе, ее задача состоит в сканировании каталога /etc/rc$runlevel.d и выполнении всех скриптов, найденных там. Сокращенная версия программы rc выглядит так:

#!/bin/sh
level=$1
cd /etc/rc.d/rc$level.d
for I in K*; do
./$I stop
done
for I in S*; do
./$I start
done

Что это означает? Это значит, что каталог /etc/rc2.d (например) содержит файлы с названиями K* — те службы, которые должны быть убиты (или остановлены), и S* — те, которые должны стартовать. Хорошо, но я еще не объяснил, откуда берутся файлы с названиями K* и S*. Каждый устанавливаемый на Ваш компьютер программный пакет, который должен выполняться на соответствующем уровне запуска, добавляет свои файлы — скрипты, запускающие и останавливающие эту программу в соответствующие каталоги /etc/rc?.d/. Чтобы избежать дублирования, все программы копируют нужные скрипты в каталог /etc/init.d и добавляют символьные ссылки на эти файлы в различные каталоги /etc/rc?.d/.
Давайте посмотрим на пример из реальной жизни — что находится в двух каталогах системы Debian:

rc1.d
K11croni K20sendmail
K12kerneld K25netstd_nfs
K15netstd_init K30 netstd_misc
K18netbase K89atd
K20gpm K90sysklogd
K20lpd S20single
K20ppp

rc.d
S10sysklogd S20sendmail
S12kerneld S25netstd_nfs
S15netstd_init S30 netstd_misc
S18netbase S89atd
S20gpm S89cron
S20lpd S99rmnologin
S20ppp

Содержимое этих двух каталогов показывает, как переход на первый уровень запуска (однопользовательский режим) убивает все задачи и запускает скрипт "single", а переход на уровень 2 (используемый по умолчанию) запускает все задачи. Число, которое появляется рядом с символом K или S, позволяет упорядочить рождение или смерть различных программ в памяти компьютера, так как маска имен файлов в скрипте /etc/init.d/rc расставляет имена этих файлов по алфавиту в порядке возрастания. Вызов команды ls -l подтвердит, что все эти файлы являются просто символьными ссылками:
rc2.d/S10sysklogd -../init.d/sysklogd
rc1.d/K90sysklogd -../init.d/sysklogd

В результате добавление новой программы означает добавление файла в каталог /etc/init.d и соответствующих символьных ссылок в каждый каталог /etc/rc?.d. Чтобы управлять поведением своей системы на различных уровнях запуска (2-й, 3-й, 4-й и 5-й по умолчанию сконфигурированы одинаково), можно просто удалять или добавлять символьные ссылки в нужных каталогах /etc/rc?.d.
Если это выглядит сложным и обескураживающим, ничего не потеряно. Используете ли Вы Red Hat или Slackware, Вы можете относиться к файлу /etc/rc.d/rc.local как к простому autoexec.bat — если Вы не так стары и можете вспомнить до-Линуксовскую эру. Если Вы используете Debian, то можете создать /etc/rc2.d/S95local и использовать его как свой собственный rc.local. Следует заметить, что Debian очень чувствителен к своим системным настройкам, так что лучше этого не делать, а если и делать, то с превеликой осторожностью.

Debian 2.0
Ко времени написания этой статьи в свет вышла версия 2.0 системы Debian, и я подозреваю, что будет уже широко использоваться, когда Вы будете читать эту статью. Хотя структура инициализации системы осталась без изменений, интересно отметить, что разработчики постарались ускорить этот процесс. Вместо непосредственного выполнения файлов-скриптов из каталога /etc/rc.d, программа /etc/rc.d/rc может сейчас просматривать (читать) их без вызова дочернего шелла. Выбор запуска либо просмотра осуществляется по имени файла — файлы с окончанием.sh просматриваются, а остальные выполняются. Этот трюк выполняют несколько строк:
case "$I" in
*.sh)
# просматриваем шелловский скрипт для скорости
(
trap — INT QUIT TSTP
set start;. $I
);;
*)
# вызов нового шелла для других программ
$I start;;
esac
Выигрыш в скорости ощутим.

Алессандро Рубини Linux Journal, issue 55,  November 1998. Перевод Игоря Греня

© Компьютерная газета

полезные ссылки
Оффшорные банковские счета