|
| ||||||||||||
| ||||||||||||
Введение в POSIX'ивизм(C) Алексей Федорчук, 2005Опубликовано на сайте LinuxCenter Глава 13. Общесистемное конфигурированиеВ главе 4 говорилось о том, что понимание принципов устройства системы незаменимо при ее конфигурировании и, главное, в отличие от знания конкретных рецептов, имеет универсальный, не зависящий от дистрибутива и даже операционки, характер. Настало время продемонстрировать это на практике. Тем более, что настройка общесистемных параметров загрузки и инициализации - необходимый этап в индивидуализации любой ОС POSIX-семейства. И для понимания этих принципов необходимо представлять, как эти самые операции - загрузка и инициализация, - происходят. Содержание
ВведениеСтарт системы распадается на два этапа, лишь опосредованно связанных между собой - собственно загрузку ее и инициализацию. Под загрузкой операционной системы понимается запуск на исполнение специальной программы, которая называется образом ядра системы (или просто ядром), а также, возможно, сопряженных с ним модулей. Как уже говорилось, образ ядра - почти обычный бинарный исполняемый файл. И специфика его запуска - только в том, что, если любые другие программы запускаются под управлением какой-либо ОС, считываясь с файловой системы, которую эта ОС воспринимает в качестве родной, то ядро обязано запуститься как бы само собой, без всякой операционки (ибо оно-то и есть операционка), и с носителя, о котором система ничего не знает (поскольку сама она еще не загружена). Не случайно в англоязычной литературы для процесса загрузки общепринята метафора называется bootstrapping, что столь же аллегорически можно перевести как "поднятие себя за шнурки своих ботинок". И хотя в реальной жизни такое не каждому удается, в мире POSIX-систем такая процедура осуществляется регулярно - и, как правило, успешно - остается только вспомнить барона Мюнхгаузена, вытащившего себя из болота, дергая за волосы... Образ ядра содержит все необходимое для чистого bootstrapping'а - загрузочный сектор, первичный загрузчик и собственно исполняемый код ядра. Однако загрузить его с нормальной файловой системы невозможно - ведь о существовании таковых ядро узнает только после того, как будет загружено. Следовательно, образ ядра должен лежать на raw-устройстве (дисковом разделе, дискете, и так далее), файловой системы лишенном. И потому такой способ применяется почти исключительно при использовании для старта Linux или BSD с загрузочной дискеты - например, для аварийно-спасательных работ. В прочих же случаях для загрузки ядра системы применяются специальные программы, именуемые, как и следовало бы ожидать, загрузчиками. Они загружают ядро системы, отвечают за определение оборудования, подгрузку соответствующих ему модулей и запуск первого процесса уже работающей операционки - процесса init. После этого в действие вступает система инициализации. Ее роль - обеспечить, посредством соответствующих стартовых скриптов (они же - сценарии инициализации), запуск основных системных процессов - сервисов, или демонов. А также - вызвать команды для получения терминала (процессы getty) и авторизации пользователей (login). Окончание старта и знаменуется приглашением к авторизации - все остальное относится уже к сфере влияния пользовательского окружения (userland). Зрительно этапы загрузки и инициализации отличаются тем или иным визуальным представлением выводимых сообщений (если вывод сообщений о ходе стартовых процессов, конечно, не отключен напрочь - в некоторых дистрибутивах Linux встречается и такое). Во FreeBSD и DragonFlyBSD, например, сообщения о ходе загрузки выводятся символами радикально белого цвета, сменяемыми на этапе инициализации обычным приглушенно-белым. В Linux картина внешне прямо противоположна - приглушенно-белая гамма в ходе старта и ярко-белая - при инициализации. А в NetBSD и OpenBSD сообщения о ходе загрузки даются на синем фоне... Загрузка и инициализация - это первое, что в любой ОС видит пользователь. Правда, пользователю POSIX-совместимой системы такое удовольствие выпадает много реже, чем "подоконнику". Нормальный режим эксплуатации домашней Unix-машины - это ее включение рано утром и выключение - поздно вечером. (Правда, представления о "рано" и "поздно" у всех свои). А служебная Unix-машина по хорошему выключаться вообще не должна - вплоть до полной физической амортизации. Ну а необходимость в рестарте системы по ходу работы в Linux или BSD возникает чрезвычайно редко. Собственно, только после пересборки и реинсталляции нового ядра (или переносе корневого раздела - но это уже вообще исключительный случай) - во всех прочих случаях реконфигурирования системы можно обойтись и без этого. Так что, казалось бы, что за дело пользователю до того, как протекает старт системы, и сколь долго он длится? Тем не менее, некоторые действия по настройке обоих этапов этого процесса бывают необходимыми. Ибо при старте системы не только выводится некоторая заставка и, возможно, меню с вариантами, но и подгружаются модули ядра, соответствующие наличному оборудованию, монтируются файловые системы, запускаются сценарии инициализации, открываются виртуальные терминалы, и так далее, и тому подобное. Конечно, безусловно обязательным из всех этих действий является только собственно загрузка ядра - прочие могут быть выполнены и впоследствии. Однако не лучше ли сразу по окончании процедуры старта получить полностью готовую к употреблению систему, нежели потом потом доводить ее вручную до этого состояния? Так что давайте проследим основные стадии ее и посмотрим, где и как (а главное - зачем) в нее можно вмешаться. О загрузке и загрузчикахНачать изучение старта системы резонно с первого ее этапа - а именно, собственно загрузки. Как уже было сказано, управление этим этапам осуществляет специальная программа, которая по русски так и называется - загрузчик. хотя в английском для нее употребляется два термина - loader и boot manager (что, как мы увидим со временем, немного разные вещи, но сейчас это не принципиально). На самом деле любой загрузчик включает в себя две или даже три относительно независимые части - даже если он распространяется в виде единого пакета, как Lilo или GRUB. Чтобы убедиться в этом, представим себе, как происходит запуск машины на "железном", так сказать, уровне (имеется ввиду - intel-совместимой персоналки, на иных архитектурах все обстоит несколько иначе). Перво-наперво после включения питания запускается программа, прошитая в ПЗУ компьютера (BIOS). Она выполняет проверку железа, после чего отыскивает носитель, установленный в BIOS Setup в качестве первого загрузочного устройства (для определенности - винчестер), на нем - первый физический блок, содержащий так называемую главную загрузочную запись (MBR - Master Boot Record). Содержимое MBR - это, во-первых, таблица дисковых разделов, тех самых четырех, в один из которых мы ранее установили DragonFly. А во-вторых - некий код, принимающий на себя управление от BIOS по окончании его работы. В стандартном MBR - том, что записан на "свежевкрученном" винчестере или восстанавливается после DOS-команды Поэтому в состав любого загрузчика должна входить программа, записываемая в MBR. Поскольку объем последнего - всего 512 Кбайт (размер физического дискового блока), из которых часть уже занята под таблицу разделов, особо богатых функций в эту программу не вместить. Обычно она способна на то, чтобы опознать все задействованные (used) первичные разделы, вывести их список и позволить пользователю выбрать раздел для загрузки, после чего передать управление на загрузочный сектор выбранного раздела. Подобно MBR, загрузочный сектор раздела (Boot Record - уже не Master!) содержит информацию о его разметке (Disk Label), зависящие от используемой в данной ОС ее схемы, и управляющий код, принимающий эстафету от программы, записанной в MBR. И этот код - вторая составная часть загрузчика. Правда, и ее возможности также не могут быть богатыми - ведь размер загрузочного сектора раздела составляет те же 512 Кбайт. И потому на нее возлагается одна-единственная функция - передать управление программе, лежащей за пределами загрузочного сектора. Которая, собственно, и должна опознать корневой раздел ОС и несомую им файловую систему, после чего, прямо или опосредованно, загрузить ее ядро. Легко догадаться, что первые две составляющие загрузчика, в сущности, не имеют отношения ни к какой операционке, и не являются частями файловой системы вообще. А вот с третьей - возможны варианты. Она может входить в файловую иерархию загружаемой ОС, как Lilo, или представлять собой нечто вроде самостоятельной мини-ОС, как GRUB (не случайно его настоятельно рекомендуют устанавливать в собственный дисковый раздел, не монтируемый по умолчанию к корню любой из загружаемых им операционок). Стадиальность загрузки системы отчетливо выражена в BSD Loader - программе, используемой для загрузки операционок этого семейства, но могущей столь же успешно использоваться в качестве мультисистемного загрузчика. Однако здесь о ней речи не будет - этой теме посвящена самостоятельная статья из цикла про DragonFly. Особенности загрузчиков Lilo и GRUBК тому же BSD Loader - далеко не самый распространенный из мультисистемных загрузчиков в свободном POSIX-мире. Многие пользователи Linux применяют в этом качестве Lilo (Linux Loader). Те же, кто по долгу или прихоти использует множество (более двух) операционных систем, да еще и меняют их, как перчатки, обычно отдают предпочтение загрузчику GRUB ( GRand Unified Bootloader). Загрузчик Lilo и его настройка - предмет подробного описания в любой толстой книге про Linux. Поэтому скажу про него лишь пару строк. Это - такой же "цепочечный" загрузчик, как и BSD Loader. То есть в общем случае он записывается в MBR загрузочного диска, откуда при старте машины опознает дисковые разделы - как первичные, так и расширенные. И если раздел несет на себе метку Linux native - загрузит с него образ ядра Linux (изначально Lilo для этого и предназначался, его функции мультисистемного загрузчика вторичны). Если же тип раздела - иной, Lilo в состоянии "по цепочке" передать управление на его загрузочный сектор, и дальнейшее будет определяться тем кодом, что записан в последнем. Тип файловой системы для Lilo по большому счету безразличен - то есть он способен загрузить ядро Linux с любой из ее многочисленных нативных файловых систем. Однако до недавнего времени он не мог выполнить эту операцию с файловой системы ReiserFS в случае, если в ней использовался так называемый tailing (или упаковка хвостов - см. главу 9). Хотя ныне это, как-будто бы изжито, при размещении ReiserFS на корневом разделе обычно все равно рекомендуется выделять специальный раздел Для разделов "чуждых" операционок тип их файловой системы для Lilo безразличен тем более - ведь, как уже было сказано, он просто передает управление на их загрузочные сектора. И поэтому, если озаботиться тем, чтобы в загрузочном секторе BSD-слайса был записан код Каждая ОС, предусмотренная для "загрузки" через Lilo (вы ведь понимаете, почему теперь я взял это слово в кавычки? - именно, потому что в полном смысле слова оно применимо только к загрузке Linux), представляет собой один из вариантов выбора в меню этой программы. Важно, что таким вариантом не обязательно отдельная операционка, - это могут быть разные дистрибутивы Linux, лежащие на собственных разделах, и разные версии ядра одной и той же Linux-системы, и просто разные сборки ядра одной и той же версии. Поэтому Lilo очень часто применяют для тестирования ядер этой системы, скомпилированных с разными опциями, или ядер разрабатываемой ветки. Варианты загрузки через Lilo описываются в его специальном конфигурационном файле - Общая секция в виде отдельных строк содержит:
Содержание отдельных секций различается в зависимости от того, предназначен этот вариант для загрузки Linux или иной ОС. В общем случае обязательными здесь будут две строки. Первая - это метка варианта (label) - его уникальный идентификатор в виде произвольной, но, желательно, мнемонически прозрачной последовательности символов, например: Секция варианта, загружающего Linux, кроме обязательного идентификатора, должна включать:
Кроме того, в Linux-секции Секции для не-Linux вариантов, как правило, не содержат ничего, кроме имени устройства несущего раздела и метки варианта: other=/dev/discs/disc0/part1 label=dos Lilo может использоваться и исключительно для загрузки единичной Linux-системы в сочетании с любым мультисистемным загрузчиком, отвечающим за загрузку систем прочих (BSD Loader, GRUB, вплоть до NT Loader). В этом случае в общей секции boot=/dev/hda1 В общей секции же секции можно раз навсегда определить имя устройства корневой файловой системы. А далее возможны и отдельные секции для вариантов загрузки, но они будут описывать уже не самостоятельные ОС, а разные версии или сборки ядра, возможно - видеорежимы или параметры ядра. Как уже было сказано, Lilo напрямую с файловыми системами не работает - даже файловыми системами Linux. Конфиг же этого загрузчика лежит в каталоге Очень просто, о существовании собственного конфига в момент запуска Lilo и не подозревает. Необходимые данные для его опознания прошиты в виде бинарного кода в загрузочном секторе - диска или раздела. И делается это одноименной командой - boot=/dev/имя_устройства в общей его секции, определяет, куда нужно записать данные - в MBR диска или загрузочный сектор раздела, и выполняет запись вариантов загрузки, завершаемую сообщением Added имя_рек где /sbin/lilo.
Сказанным в предыдущих абзацах определяются и два принципиальных ограничения на использование Lilo вообще. Первое вытекает из положения конфига этого загрузчика внутри файловой системы Linux. Так что для изменения его конфигурации из другой операционной системы необходимо иметь доступ к той файловой системе, на которой лежит корень инсталлированного Linux'а, причем в режиме записи. И если примонтировать Ext2fs/Ext3fs к файловой системе FreeBSD или DragonFlyBSD в режиме read/write можно без проблем (ныне это не потребует даже пересборки ядра и той, и другой ОС), то доступ из любой ОС BSD-семейства к разделам с ReiserFS или XFS в настоящее время невозможен (и неизвестно, будет ли возможен в обозримом будущем). Конечно, можно взять за правило размещать корневую систему Linux только на разделе с Ext2fs/Ext3fs. Однако второе ограничение - необходимость перезапуска Есть и третье ограничение, не столь важное: относительно слабые (по сравнению с GRUB) интерактивные возможности. Конечно, Lilo позволяет в режиме командной строки вмешиваться руками в ход загрузки - но только загрузки Linux же (например, передавать параметры ядру). Да и то - в ограниченном объеме. Возможности же вмешательства в ход загрузки чужой ОС вообще заканчиваются в момент выбора соответствующего ей варианта. Раз уж речь зашла об ограничениях Lilo, то, пользуясь случаем, подчеркну: прочие ограничения, на которые можно нат олкнуться в литературе, как то: невозможность загрузить ядро Linux с области диска, лежащей за пределами первых 1024 его цилиндров, или с логического раздела в разделе Extended DOS, - давно потеряли силу. И пользователь любого современного дистрибутива о них может смело забыть. Так что основная сфера применения Lilo - это работа преимущественно (или исключительно) в Linux, при эпизодическом использовании какой-либо другой ОС. Причем рискну предположить, что под другой ОС будет выступать, скорее всего, какая-либо из версий Windows. Экспериментирование же с многочисленными операционками разных семейств - это, по моему мнению, прерогатива GRUB. Как и Lilo, GRUB неоднократно был предметом описания в различных (преимущественно онлайновых) документах. Наиболее полное (из числа мне известных) содержится в цикле статей Владимира Попова, который можно найти здесь: http://unix.ginras.ru/linux/base011.html. К которой я отсылаю любознательного читателя, затронув ниже лишь основные особенности и возможности этой программы. Если Lilo, как и следует из его названия, создавался в первую очередь для загрузки Linux при сохранении возможности старта Windows, то целью разработчиков GRUB изначально было создание универсального мультизагрузчика, максимально независимого от любой операционной системы. История его началась в 1995 году, когда операционная система GNU Hurd (микроядерная ОС светлого будущего, столь же отдаленного, как и коммунизм в мировом масштабе) достигла той степени развития, что могла уже быть загружена. И встал вопрос - каким же образом это сделать, так как существовавшие тогда загрузчики оказались на это неспособными. Конечно, с точки зрения идеологии GNU, логично было бы изобрести для этой цели собственный (еще один) загрузчик, в полной мере отвечающий идеалам свободы и демократии. Однако, к счастью для всего прогрессивного человечества, был избран иной путь: Multiboot Specification - универсальный метод загрузки ядер, этой самой спецификации соответствующих. Причем сама спецификация бралась отнюдь не с потолка - в ее основу легли особенности существующих ядер Linux и BSD-систем. Ведь, как я уже говорил, файлы их образов самодостаточны для запуска и несут в себе всю необходимую информацию - и дело упирается только в то, что в обычной ситуации они расположены на носителе с файловой системой, поддержка которых начинается только после загрузки соответствующего ядра. Так что суть универсальности предложенного метода и заключалась в том, чтобы загрузчик получил средства доступа к файловой системе. Зримым же, действительно универсальным, воплощением Multiboot Specification и стал мультисистемный загрузчик GRUB. Собственно, единственным его ограничением для полноценного использования (ниже станет ясно, что "неполноценное" использование GRUB вообще ничем не ограничено) была совместимость с файловой системой загружаемой ОС. Ибо, в отличие от BSD Loader и Lilo, GRUB способен работать с очень многими файловыми системами напрямую, без всякого использования ресурсов соответствующей операционки - "монтировать", читать с них данные, подвергать их редактированию и записывать изменения. Что превращает его в своеобразную мини-ОС, имеющую к тому же свой собственный, шелл-подобный, интерфейс пользователя. Можно выделить две степени совместимости GRUB с файловыми системами - полную и частичную. Полностью совместимые файловые системы - это те, что способны нести GRUB сам по себе. И в их числе - абсолютно все нативные файловые системы Linux (включая JFS, имевшие некогда место проблемы с "монтированием" ReiserFS, насколько я знаю, в прошлом), Minix и FAT. То есть загрузчик GRUB может стартовать с любого носителя, отформатированного соответствующим образом - дискового раздела, дискеты Linux (на которых применяется файловая система Minix) или DOS (с файловой системой FAT). Хотя по причинам, которые скоро станут понятны, разработчики рекомендуют размещать GRUB на самостоятельном разделе с файловой системой Ext2fs. Частично совместимые с GRUB файловые системы сами по себе нести его не могут. Но после своего старта он способен их идентифицировать, прочитать и загрузить с них ядро, если оно отвечает Multiboot Specification. И в эту группу попадают практически все файловые системы свободных операционок, внутренний формат которых общедоступен - кроме Linux, тут мы видим также все варианты FFS и UFS, используемых BSD-семейством. Если же какая-то из таких файловых систем (как правило, из числа только что созданных) кажется несовместимой с текущей версией GRUB - это исключительно временное явление. Потому что для любой открытой файловой системы нет никаких препятствий получить свою поддержку в GRUB. Приведу пример: с появлением 5-й ветки FreeBSD она обрела новую нативную файловую систему, UFS2, несколько отличную от прототипа - UFS просто. В результате единовременная версия GRUB (0.93) оказалась неспособной работать с ней напрямую (ниже я покажу, что это все равно было обходимо). Однако уже для версии 0.94 появился патч поддержка UFS2, а с версии 0.95 GRUB поддерживает эту файловую систему, что называется, "из тарбалла". Можно видеть, что в списке частично совместимых с GRUB файловых систем нет тех, что созданы Самой Великой Софтверной компанией, в частности - всех вариантов NTFS. Что понятно - ведь их внутреннее устройство - тайна за семью печатями. Однако мир свободного софта в очередной раз подтверждает справедливость утверждения, что на самое хитрое ухо (вариант для дам) всегда найдется болт с левой резьбой. Существует он и здесь: операционки, файловые системы которых для GRUB недоступны, могут быть загружены "по цепочке" - передачей управления на загрузочный сектор соответствующего раздела. Тот же способ можно применить и для загрузки свободных ОС, файловые системы которых временно не поддерживаются на моей памяти таковыми бывали периодически некоторые версии OpenBSD и FreeBSD 5-й ветви. К слову сказать - даже "ухо с закоулками" (несовместимость ядра с Multiboot Specification, имеющая место для DOS/Windows9X/ME) не оказывается помехой для винта от GRUB. И указанные операционки могут быть столь же успешно загружены "цепочечным" методом. Таким образом, универсализм GRUB в рабочем (то есть установленном и настроенном) состоянии сомнений не вызывает. Однако с точки зрения установки и настройки он предстает столь же независимым от любой ОС. Ибо устанавливается он с самодостаточной загрузочной дискеты. А с недавнего времени, благодаря усилиям Владимира Попова, это можно проделать и с мультизагрузочного LiveCD (который можно скачать отсюда). То есть: наличия инсталляции какой-либо ОС (или дистрибутива Linux не требуется). Что же касается конфигурирования GRUB, то, если следовать приведенным ранее рекомендациям разработчиков (установке GRUB на отдельный дисковый раздел с файловой системой Ext2fs - и резоны к тому сейчас прояснятся), то и тут никаких сложностей не предвидится ни в одной из свободных ОС. В Linux этот раздел монтируется как каталог За настройку загрузки GRUB отвечает специальный файл, доступный из Linux как Так что для конфигурирования же GRUB из какой-либо иной ОС требуется только возможность чтения раздела с Ext2fs и записи в него. А, как уже говорилось, получить такую возможность из FreeBSD и DragonFlyBSD ныне никакого труда не составит (да и в случае Net- или OpenBSD в худшем случае потребуется только пересборка их ядер). Так что рекомендация разработчиков о выборе файловой системы загрузочного раздела становится понятной - прочие файловые системы Linux BSD-семейством не поддерживаются, а FAT... ну он FAT и есть, всерьез говорить о нем не стоит. Таковы основные особенности (и возможности) GRUB. О деталях его установки, настройки и интерактивной работы в ходе загрузки можно было бы написать еще много. Однако это уже проделано Владимиром Поповым, и повторяться я не буду. Памятуя и о прекрасной штатной документации этой программы, правда, в нелюбимом мною формате ( # Config file for GRUB - The GNU GRand Unified Bootloader # /boot/grub/menu.lst # Общая конфигурация загрузчика timeout 5 # Время ожидания выбора загружаемой ОС в секундах default 0 # ОС, загружаемая по умолчанию # (в данном случае Linux) color light-blue/black light-cyan/blue # Цветовая гамма меню (мне такая нравится) # Секция, отвечающая за загрузку Archlinux # (0) Arch Linux title Arch Linux [/boot/vmlinuz] # Идентификатор ОС # он же - пункт меню загрузчика root (hd0,1) # Устройство, несущее корневую файловую систему: # 2-й раздел 1-го диска в нотации GRUB # В нотации Linux ему соответствует устройство # /dev/discs/disc0/part2 в следующей строке kernel (hd0,0)/vmlinuz root=/dev/discs/disc0/part2 ro # где # (hd0,0)/vmlinuz - положение файла образа ядра # на загрузочном устройстве в нотации GRUB - # 1-м разделе 1-го диска # root=/dev/discs/disc0/part2 # имя устройства с корневой файловой системой # уже в нотации Linux (при использовании devfs) # ro - предписание монтировать его в режиме read-only А в ближайшей же интермедии я остановлюсь на вопросе, недостаточно освещенном в источниках - загрузке с помощью GRUB систем BSD-клана (в том числе и при отсутствии доступа к их файловой системе). Задачи инициализацииИтак, тем или иным способом загрузка ядра и всего сопутствующего ему хозяйства успешно завершена. В дело вступает главный калибр любой POSIX-системы - процесс init. Это первый (в прямом и переносном смысле его PID равен единице) пользовательский (то есть работающий в пользовательском пространстве ядра, юзерланде, процесс, и запускается он исполнением одноименного файла В действительности это могут быть (и в разных системах действительно бывают) весьма разные программы. Более того, его можно подменить при интерактивном управлении процессом загрузки другой программой, например, командной оболочкой. Однако это сейчас не очень важно - рассмотрим только штатные задачи программы Первой из таких задач, как по времени исполнения, так и по значению, является проверка целостности наличных файловых систем. Для начала каждая из них проверяется на наличие бита "чистого размонтирования" (clean byte), который автоматически устанавливается в ходе правильного завершения предыдущего сеанса работы. Если такой бит обнаруживается на каждой файловой системе - все хорошо, дело движется дальше. Если нет - возможны варианты, о которых я скажу позднее. Следует отметить, что сам по себе "бит чистого размонтирования" отнюдь не гарантирует сохранности файловой системы и, особенно, ее данных. Он лишь показывает, что файловая система была корректно размонтирована в предыдущем сеансе. В этом случае процесс init делает не лишенное резона допущение, что с метаданными и данными ее все в порядке, и переходит к выполнению следующей задачи. А следующая задача процесса init - это вызов и отработка сценариев инициализации, или стартовых скриптов, собранных в каталоге Команды, образующие стартовые сценарии, получают свои опции, их значения и аргументы из специальных файлов конфигурации, также имеющих своим местопребыванием Сказанное может показаться не очень понятным, поэтому попытаюсь продемонстрировать на примере. Например, обязательная процедура на стадии отработки сценариев инициализации - монтирование необходимых файловых систем в режиме чтения/записи; и перемонтирование - ведь при загрузке ядра несущая его корневая файловая система монтируется в режиме "только для чтения". Это выполняется прямой директивой $ mount -a предписывающей смонтировать все файловые системы, и входящей в состав одного из стартовых сценариев (каком именно - зависит от оперционки и дистрибутива). А вот что понимается под словом "все" (имя опции Это - очень простая база данных, каждая запись которой соответствует подлежащей монтированию файловой системе, а поля, разделителем которых являются символы пробела (пробелов) или табуляции, следующие: имя файла устройства, несущего файловую систему; точка монтирования - каталог в файловой иерархии; тип файловой системы; опции монтирования (часто имеет значение default). Содержимое первых двух полей каждой записи передается команде Последовательное разделение стартовых сценариев и их конфигурационных файлов - один из краеугольных принципов общесистемного конфигурирования. В сущности, пользователю при нормальном ходе настройки практически нет необходимости ни знакомиться с содержимым скриптов (хотя это и не вредно), ни, тем паче, менять в них что-либо (последнее допустимо только в том случае, если этот самый пользователь точно знает, что делает, иначе систему легко довести до неработоспособного состояния). А вот вносить изменения в значения параметров конфигурационных файлов - не только можно, но и нужно - разумеется, такое разрешение не избавляет пользователя от понимания смысла своих действий. Наконец, третья непременная задача процесса init - теч, что в главе 7 мы рассмотрели как получение терминала (запуск процесса getty), установку его свойств и подготовку к авторизации - вытеснение его процессом login. Эта процедура также по разному выполняется в разных системах, хотя тут многообразие не столь и велико, как при отработке стартовых скриптов. В ходе инициализации могут выполняться и некоторые другие задачи, скажем, конфигурирование приложений, не входящих в базовую систему, но, тем не менее, запускаемых в качестве стартовых сервисов (демонов). Поскольку такие программы устанавливаются отдельно от системы (и не в обязательном порядке), сценарии их запуска и сопряженные с ними конфиги лежат не в каталоге Описанная последовательность инициализации происходит при бессбойном ее протекании - если ни на одной из стадий не происходит ошибок. Если же таковые случаются - по причине аппаратных ли сбоев или ошибок пользователя при настройке, - все может протекать совершенно иначе. Первый потенциальный источник ошибок инициализации - отсутствие "бита чистого размонтирования", выявляемое при начальной проверке файловых систем. В этом случае делается вывод о некорректности завершения предыдущего сеанса и возможности существования противоречий в ней. Таковыми могут быть, например, записи в каталогах, которым не соответствуют идентификаторы каких-либо файлов. Или, напротив, идентификаторов файлов, не приписанных ни к каким каталогам. Для проверки, действительно ли такие противоречия имеют место быть (а отсутствие clean byte отнюдь не влечет их неизбежности) и, при необходимости, исправления выявленного безобразия, запускается утилита проверки файловой системы Ошибки при отработке скриптов инициализации также влекут разные последствия. Обычный (и наиболее легкий) случай - что сервис, в сценарии запуска которого произошла ошибка (а она может быть вызвана, например, неправильны указанием опций или аргументов в соответствующем конфиге), просто не будет доступным после загрузки системы. Например, так будет с демоном консольной мыши в Linux - Более серьезные последствия будут иметь ошибки при монтировании файловых систем, самый частый источник которых - синтаксически неправильное их описание в файле Наконец, ошибки в процессе получения терминала (возможные при экспериментах, например, с автоматической регистрацией в системе). Они также достаточно неприятны, и, как правило, приводят к невозможности начала нормальной работы. Впрочем, оснований для паники нет - даже при впадении в панику ядра, все возможные при инициации системы ошибки исправимы тем или иным способом. Ибо легкий флирт, в том числе и с операционной системой, подобно насморку, переносится на ногах, и постельный режим необходим лишь в тяжелых случаях. В одних ситуациях достаточно завершить процесс загрузки и чуть подправить конфиги, в других - загрузиться в однопользовательском режиме и провести проверку и ремонтирование файловых систем вручную, в третьих придется грузиться с rescue-носителя (например, LiveCD). А вот хирургического вмешательства - сиречь полной переустановки системы, - скорее всего, не потребуется никогда. Впрочем, все это будет предметом отдельного разговора в одной из ближайших интермедий. Оборотная сторона инициализации системы - это ее останов или рестарт, различий между этими процессами практически нет. И отвечает за него команда $ shutdown -h now или $ shutdown -r now соответственно. Во всех, насколько мне известно, POSIX-системах существуют также команды Останов системы происходит в порядке, обратном ее инициализации. Сначала делается попытка корректного завершения всех пользовательских процессов отправкой им сигнала TERM. По истечении некоторого промежутка времени всем еще "живым" процессам отправляется сигнал KILL - для гарантированного их убиения. Затем стопорятся все стартовые сервисы и демоны. Наконец, содержимое дисковых кэшей записывается на диск (посредством команды sync), и размонтируются файловые системы. После этого обычно появляется сообщение о возможности безопасного отключения питания машины или оно отключается автоматически. При рестарте все происходит точно также, но после останова системы автоматически начинается перезагрузка машины. Весь процесс останова и (или) рестарта определяется соответствующим сценарием (или сценариями), подобными сценариям инициализации. Важно - и это одно из первых правил техники безопасности, - что Unix-машину крайне не рекомендуется останавливать простым отключением питания. Каковое чревато разными неприятностями. Это могут быть
В современных версиях POSIX-систем в той или иной мере реализована поддержка управления питанием стандарта ACPI (Advanced Configuration and Power Interface). При ее включении в принципе становится допустим останов системы простым отключением питания машины - на нажатие кнопки Power на корпусе компьютера система реагирует точно так же, как и на команду Стили инициализацииМое описание инициализации POSIX-системы поневоле получилось чрезвычайно обобщенным. Попробую перейти к конкретике, для чего нам потребуется представление о стилях... нет, не работы, как говорил товарищ Мао, а инициации. Стилей инициации, опять же, вопреки председателю КПК, не три, а два: BSD-стиль, повсеместно принятый в одноименных системах, и стиль System V, используемый в большинстве распространенных дистрибутивов Linux. Впрочем, Великий Кормчий не так уж и не прав. Потому что в некоторых дистрибутивах Linux, при сохранении родовых пятен System V (таких, как уровни выполнения, о которых будет говориться далее), применяются BSD-подобные стартовые сценарии, и это вполне можно считать третьим, промежуточным, стилем. Это - размежевание лишь в первом приближении. Потому что сценарии инициализации в стиле System V - это та сфера, в которой майнтайнеры отдельных дистрибутивов Linux в своем стремлении к оригинальности оттягиваются по полной программе. Инициация в BSD-стиле, что в одноименных системах, что в дистрибутивах Linux, подвержена этой тенденции существенно в меньшей степени. Опять перефразируем нашего великого автора: пользователи всех BSD-схем счастливы одинаково, пользователи схем загрузки SysV - несчастливы по своему. Впрочем, приверженцы последнего стиля инициации, скорее всего, поменяли бы мои определения местами... Особенности BSD-стиляНачнем с чистого BSD-стиля, как более простого, прямолинейного и потому более доступного пониманию начинающего пользователя (да и, по моему глубокому убеждению, более ему подходящего). Начать с того, что он предусматривает всего два режима загрузки - однопользовательский, предназначенный для аварийно-восстановительных работ и решения некоторых задач администрирования, и многопользовательский, при котором осуществляется вся нормальная деятельность пользователя. В однопользовательском режиме загрузка происходит а) при выборе соответствующего пункта (Boot in single user mode) в меню начального загрузчика, б) при задании команды В любом случае при загрузке в однопользовательском режиме не монтируется ни одна файловая система из При загрузке в многопользовательском режиме (а она осуществляется по умолчанию при нормальном включении машины или ее перезагрузке) все стадии инициации проходятся по полной программе: монтируются предназначенные к тому файловые системы из файла Между однопользовательским и многопользовательским режимами не лежит непреодолимой пропасти: переход из одного режима в другой возможен не только при рестарте машины, но и в ходе одного сеанса. Для немедленного перехода в однопользовательский режим служит команда $ dhutdown now Возврат обратно в многопользовательский режим происходит по команде $ exit Такой способ широко применяется для реинициализации системы без полной ее перезагрузки после изменения каких-либо конфигурационных параметров - он протекает гораздо быстрее последней. Нужно только помнить, что при этом не все сервисы и демоны обязаны работать правильно. Загрузка в многопользовательском режиме - и это отличительная особенность BSD-стиля, - потенциально влечет за собой доступность для запуска абсолютно всех системных служб и демонов: инициализирующие их сценарии (располагающиеся в каталоге При установке системы, использующей BSD-стиль инициализации, в каталог servicename_enable="значение" или переменная="значение" Значение строк первого вида = "YES" или "NO". Легко догадаться, что они разрешают (или запрещают) запуск поименованного сервиса посредством соответствующего ему (и, как правило, одноименного) сценария из каталога moused_enable="YES" разрешает запуск службы консольной мыши посредством скрипта Значения же строк второго вида - это параметры, передаваемые командам, входящим в скрипты инициализации. Так, строки moused_type="auto" moused_port="/dev/ums0" определяют что значения опций Как правило - и это тоже традиция BSD-систем, - по умолчанию в файле /etc/rc.conf разрешен запуск лишь минимально необходимого для начала работы количества системных служб. Большая же их часть обычно запрещена - или явным образом, указанием значения "NO", или по умолчанию а откуда они берутся - мы скоро увидим). Так что включение необходимых пользователю демонов (например, той же консольной мыши) - дело рук самого пользователя. Откуда берутся стартовые умолчания? А берутся они из файла В общем виде это делается, например, так: в одной виртуальной консоли (на которой нужно зарегистрироваться как root или получить его права командой $ less /etc/defaults/rc.conf И нужные строки из последнего просто переносятся в первый, где и модифицируются должным образом. Не вредно при этом задействовать и третью пользовательскую консоль - для чтения Что же касается заключительной стадии BSD-инициации - процесса получения терминала, - то она контролируется записями в файле Как уже говорилось, сценарии, отвечающие за запуск стартовых сервисов, находятся в каталоге Ход процесса останова системы определяется сценарием Стили System VОснову инициализации в стиле System V, в более или менее чистой форме принятой в Linux, составляет понятие runlevels. Это один из тех терминов, любой русский перевод которого способен только сбить с толку начинающего пользователя. Потому что часто используемые переводы типа уровни запуска или уровни загрузки создают впечатление, что система в процессе инициализации последовательно проходит некие, соответствующие им, стадии. На самом деле, как мы видели, стадии инициализации действительно имеют место быть - вот только к runlevels они имеют отношение весьма косвенное. Понять, что же такое runlevels в System V проще всего в сравнении с BSD-инициализацией. В которой, как мы только что видели, существует два режима - однопользовательский, при котором не исполняются никакие стартовые сценарии, и многопользовательский, при котором исполняются все сценарии, разрешенные в главном конфиге Вызов runlevels, то есть метасценария для группы сценариев, осуществляется при инициализации системы первым ее пользовательским процессом - процессом init. А сами эти метасценарии описаны в главном конфигурационном файле этого процесса - Теоретически процесс init предусматривает вызов семи runlevels - от нулевого до шестого; за тремя из них зафиксированы метасценарии определенного назначения, использование остальных отдано на откуп создателям дистрибутивов (и, как я уже говорил, они используют это на всю катушку). зарезервированы следующие runlevels:
Что в очередной раз показывает неадекватность из приведенных выше переводов: русскоязычному пользователю, не совсем лишенному элементов логического мышления, трудно понять, почему останов системы отнесен у ровням ее запуска (хотя я вполне допускаю, что у пользователя, родной язык которого - английский, слово runlevel вызывает совсем другие, "правильные" ассоциации). Хотя почему останов и перезагрузка системы вообще выступают в одном ряду с режимами ее запуска - понять вообще невозможно, даже отвлекаясь от перевода, - но это уже фирменный стиль System V. Опять, однако, отвлекся - вернусь к прочим runlevels. Их использование - свободно. Как правило, один из свободных номеров (обычно 3 или 4) задействуется под нормальный многопользовательский режим работы, другой же (4 или 5) - под режим запуска Иксового сеанса (то есть графический). В некоторых дистрибутивах предусматривается еще и многопользовательский режим без поддержки сети. Вот как это выглядит в наиболее распространенном из дистрибутивов Linux - Red Hat (в замужестве - Fedora Core):
В других дистрибутивах Linux количество задействованных runlevels в интервале со 2-го по 5-й и их соответствие режимам может быть иным: для конкретного дистрибутива это можно посмотреть в файле А вообще описание действий по инициализации в файле Следующее действие из предписанных id:3:initdefault: и автоматически влечет за собой исполнение набора скриптов, за ним закрепленных. Скрипты эти сгруппированы в определенных (точнее, очень неопределенных - то есть своих в каждом дистрибутиве) подкаталогах каталога Возникает вопрос - а не повторяются ли сценарии в подкаталогах разных runlevels? Ведь очевидно, что для запуска многопользовательского режима без поддержки сети, полного многопользовательского режима и режима графического нужно выполнить существенно пересекающееся множество действий. И различия лишь в том, что во втором случае добавляется запуск сетевых служб, а в третьем - еще и менеджера графического входа в систему (например, Ответ, как ни странно, будет отрицательным. Потому что на самом деле реальных сценариев, соответствующих runlevels, в указанных каталогах нет. Все стартовые скрипты собраны в отдельном подкаталоге с именем вроде Более того, в каждом runlevels-каталоге ссылки эти имеются в двух экземплярах - одна ссылка маркированная буквой Порядок запуска стартовых сценариев при рассматриваемой их схеме может быть важен: очевидно, что отдельные сетевые службы могут быть запущены только после включения общей поддержки сети. И обеспечивается этот порядок двузначными цифрами в именах ссылок (но не самих скриптов) в каждом runlevels-каталоге: чем меньше цифра, тем раньше запускается сценарий, которому эта ссылка соответствует. Осталось определить, откуда берутся значения опций и аргументов для команд, образующих сценарии инициализации. А берутся они из собственных конфигурационных файлов - ведь принцип разделения скриптов и конфигов неукоснительно проводится и в схеме SysV. Конфиги эти могут быть собраны в едином подкаталоге типа Наконец, с запуском сценариев инициализации покончено. Остается последнее из предписанных процессу init действий - получение терминалов. В схеме SysV оно также описывается в файле # Run gettys in standard runlevels 1:2345:respawn:/sbin/mingetty tty1 2:2345:respawn:/sbin/mingetty tty2 3:2345:respawn:/sbin/mingetty tty3 4:2345:respawn:/sbin/mingetty tty4 5:2345:respawn:/sbin/mingetty tty5 6:2345:respawn:/sbin/mingetty tty6 Впрочем, разговор на эту тему уже был - в Интермедии 13. Добавлю только, что в данном примере 6 виртуальных терминалов активизируются при всех runlevels (кроме однопользовательского режима, разумеется, останова и перезагрузки). А при вызове runlevels 5 (напомню, здесь это - X-сессия) на первой же свободной (то есть не активизированной) консоли запускается менеджер графического входа в систему, за что отвечает такая строка: x:5:respawn:/etc/X11/prefdm -nodaemon Я попытался дать максимально обобщенное описание процесса инициализации в стиле System V. Насколько получилось - судить не мне. Однако более ясное представление о ней можно получить, только рассматривая реализации в конкретных дистрибутивах, на что у меня нет ни желания, ни возможности. Так что заинтересованным читателям остается только обратиться к дополнительным источникам информации. Из которых я выделил бы Linux Startup Manual) - с той только оговоркой, что слово Linux в его заглавии следовало бы заменить на Red Hat: ибо в нем описана схема инициализации именно этого дистрибутива. А за более обобщенным описанием схемы SysV и принципов построения собственной схемы загрузки в этом стиле следует обратиться к LFS Book Герарда Бикманса (http://hints.linuxfromscratch.org/) или какому-либо из ее русских переводов: 4-й (http://multilinux.sakh.com/lfs/) или 5-й (http://linux.yaroslavl.ru/docs/book/lfsbook/) версии, номер здесь принципиального значения не имеет. Схема инициализации в стиле System V может показаться излишне усложненной. Хотя, по словам лично мне знакомых администраторов сетей, позволяет очень гибко управлять различными сервисами. Однако для конечного пользователя такое усложнение неоправданно. И, как выяснилось, это мнение не только мое. Иначе чем объяснить стремление прикрутить сценарии инициализации в BSD-стиле в ряде современных дистрибутивов Linux, таких, как Gentoo, CRUX, Archlinux, не говоря уже о дедушке дистрибутивостроения - Slackware. Разумеется, и в этом случае никуда не деваются ни runlevels, ни |
|
CITForum © 1997–2025