Самостройный Linux
Часть 1, Вводная

Алексей Федорчук
[email protected]

Я столько времени писал о всяких Linux'ах, а также Free- и прочих BSD, что однажды в голову закралась шальная мысль - а не замахнуться ли на сборку своей собственной системы? Той самой, которая станет очередной ступенькой на пути к недосягаемому идеалу? А что, и замахнемся, - ответил я себе, и, по мере сил и возможностей, приступил к изучению вопроса. Результаты вылились в нечто похожее на

Исторические изыскания

Оказалось, что я не одинок в своем стремлении: мысль стать обладателем собственной уникальной системы приходила в голову многим. В Сети обнаружились упоминания о двух проектах под значимыми названиями Linux from Scratch (что в данном случае я перевел бы как "Linux по сусекам скребеный", сокращенно - LFS) и BYO Linux (то есть нечто вроде - "Построй свой собственный Linux").

Основоположник LFS - Герард Бикманс (Gerarg Beekmans). Устав от изобилия дистрибутивов, ни один из которых не удовлетворял его в полной мере, он решил собрать систему, в которой было бы только то, что он сам установил - и ни граном больше. Что и не замедлил претворить в жизнь.

Произведение Герарда назвать дистрибутивом в общепринятом понимании термина трудно. Это - не distribution на все случаи жизни, а, скорее, сборник рецептов, как, опираясь на исходники base Linux, построить собственную систему. Забегая вперед, замечу - построение это будет стопроцентно удачным только в том случае, если следовать писанию Герарда (знаменитой LFS Book, доступной ныне и в русском переводе), аки священному. И при этом пользоваться именно теми версиями базового софта, которые описаны им в соответствующей версии книги - в противном случае возможны всякие неожиданности.

Менее известен другой проект - BYOLinux. Начатый Джонатаном Торпом (Jonatan Thorpe) практически одновременно с LFS, ныне он прекратил свое развитие. Впрочем, описание Джонатана можно использовать как руководство к действию и до сих пор (с поправкой на версии софта, разумеется). Оно не столь детально, как LFS Book, однако, уже с силу этого, носит несколько более общий характер.

А в последнее время идея системного самостроя проникла и мир BSD-систем: на DaemonNews можно обнаружить статью Йенса Швайкхардта с характерным названием - FreeBSD from Scratch (спасибо Максиму Чиркову и его сайту за ссылку). В ней он подробно описывает процесс сборки из исходников FreeBSD целиком - от Distributions до необходимых ему портов, - методом, отличным от штатного rebuild'а системы (но зато сходным с методом Герарда).

А вообще говоря, основоположник системного самосбора - не кто иной, как Линус Торвальдс: не из (собственноручно написанных) исходников ли собирал он свою первую Linux-систему? Впрочем, разработчики Free- и NetBSD также были вынуждены воссоздавать свои системы с нуля после запрета использования кода BSD4.4...

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

Постановка проблемы

Как собирать Linux из исходников? Тут возникает извечная проблема курицы и яйца. Действительно, чтобы собрать компилятор, нужно как минимум иметь компилятор, а чтобы собрать bash - требуется этот компилятор запустить (из командной строки bash, разумеется). А и то, и другое требует библиотечных функций из главной системной библиотеки glibc. Которую, как нетрудно догадаться, также следует предварительно скомпилировать. Иными словами, как говорил мой бывший воинский начальник, "чтобы сварить суп из курицы, нужно как минимум иметь курицу". Что в данном случае означало - чтобы собрать работоспособную Linux-систему, ее уже нужно иметь в установленном (и работоспособном) виде.

Получается заколдованный круг, выход из которого - не столь очевиден. Линус на заре создания своей ОС решил эту систему просто: первые варианты Linux'а собирались под управлением другой операционной системы (волею судеб ею оказалась Minix знаменитого теоретика осестроения Энди Таненбаума). Однако ныне можно обойтись без этого, собирая Linux из Linux'а же.

Этим путем пошли и Герард, и Джонатан. То есть имея работоспособную Linux-машину в произвольном исполнении и полный набор исходников base Linux. Установленный дистрибутив может быть любым (при условии достаточной свежести компилятора gcc и библиотеки glibc, прочие компоненты не столь критичны). Ну и ядро родительской системы должно поддерживать все опции, желательные для системы дочерней (в первую очередь файловую систему, на которой предполагается разместить корень ее файловой иерархии).

По методу Герард сначала собирается (на отдельном дисковом разделе) некий самодостаточный минимум - bash, gcc, binutils и т.д., причем - статически слинкованные. Далее выполняется операция chroot и посредством этих программ собирается библиотека glibc. А потом - перекомпилируется, уже в динамически связанном виде, все ранее собранное хозяйство, плюс дособирается остальное из base Linux, ядро системы и средства загрузки.

Основная трудность здесь - в сборке библиотеки glibc: если она завершится успешно, с остальными компонентами также все будет в порядке. Однако именно в этом-то деле успех (по причинам, о которых речь пойдет в одной из следующих частей) и не гарантирован. Так что Джонатан вообще отказывается от этого шага, предлагая просто перенести бинарный пакет glibc родительской в дочернюю и устранить его обычным для прекомпилированных пакетов образом.

Собственно говоря, основная заслуга Герарда, на мой взгляд, в разработке идеологически чистого метода сборки glibc, осуществляемого с помощью разработанных им специальных патчей. Однако метод этот жестко привязан к версии главной системной библиотеки: текущие патчи его не работают с более свежими версиями glibc.

Мне же хотелось осуществить самострой системы а) идеологически чисто (то есть без заимствования компонентов родительской системы, б) из базовых компонентов произвольных (то есть наиболее свежих на текущий момент) версий (ведь не секрет, что многие из них обновляются достаточно часть, и, главное, в) на чистую машину. Не то чтобы у меня на винчестере не было какого-либо Linux'а - был, и являлся им Gentoo Linux. Более того, я даже осуществил самосбор, используя этот дистрибутив в качестве родительского, - и осуществил успешно. Но вследствие этого успеха появилось желание разработать общий метод самосбора действительно с нуля (в том числе и на только что купленный компьютер).

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

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

Таким образом, Lonix идеально подходил на роль слесарного чемоданчика. Однако для этой цели подошел бы, вероятно, и knoppix. Более того, подозреваю, что можно осуществить самосбор и с опорой на установочный LiveCD Gentoo и его первый (stage1) тарбалл, однако это пока не проверено.

Выбор компонентов

Это - второй вопрос системного самостроя. Очевидно, что в такой системе, как в рюкзаке хорошего туриста, не должно быть ничего лишнего (на то десятидисковые дистрибутивы имеются), но все необходимое - должно быть. То есть содержимое моего рюкзака должно обеспечивать не только загрузку системы, но и средства для ее наращивания, а также решения насущных практических задач. В результате сложился (пока у меня в голове) некоторый самодостаточный набор, который можно назвать Base Linux.

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

В свою очередь, непременные компоненты также можно разделить на безальтерантивные и те, для которых возможен выбор из нескольких вариантов. В число первых попадают ядро Linux (еще бы - если бы у бабущки был... сами знаете что, она звалась бы дедушкой) и тесно связанный с ним комплекс утилит управления дисковыми разделами (linux-utils), загружаемыми модулями (modutils), обязательно задействуемыми файловыми системами (ext2fsprogs, procinfo и родственными, чисто волюртаристически я включил бы сюда и devfsd - без файловой системы устройств нынче не житье). Фактически нет выбора и для инструментов работы с файлами, от fileutils до архиватора tar и компрессоров gzip и bzip2 (причем последние два - не альтернатива, а неизбежность), утилит обработки текстов (grep, gawk, sed, diffutils, patch - в данном контексте они выступают как средства обеспечения работы установочных сценариев), базовых средств поддержки сети (netkit и т.д.). Ну и конечно инструментарий собственно для сборки (gcc, binutils, make и тому подобный) плюс основные системные библиотеки (от glibc до ncurses и zlib).

Альтернативно-обязательные компоненты определяются пользовательскими предпочтениями и потребностями. Среди них в первую очередь упомяну патчи ядра для расширения его функциональности (например, для поддержки XFS, EVMS и тому подобных продвинутых возможностей, не удостоившихся пока включения в каноническое ядро). Далее - инструментарий для работы с файловыми системами, отличными от ext2fs, начиная с той же xfsprogs и заканчивая системами управления логическими томами (пакеты lvm-user и evms), пакеты управления консолью (традиционный выбор между kbd и console-tools), средства управления системными сообщениями (sysklogd или его более продвинутые аналоги типа metalog) и контроля над пользовательскими аккаунтами (впрочем, в Linux этой цели обычно служит пакет shadow).

Как ни странно, достаточно альтернативен и выбор средств обеспечения загрузки системы, начиная с собственно загрузчиков (GRUB или LILO, не говоря уже о сторонних), и заканчивая системами инициализации: конечно, в Linux обычно традиционно используется пакет sysvinit (стартовая система в стиле System V), но никто ведь не может запретить и старт в BSD-стиле.

Наконец, последний штрих к обязательному натюрморту - командная оболочка (шелл, по простому). Здесь теоретически также не обязательно замыкаться на bash, можно бы взять любую POSIX Shell-совместимую. Однако на практике весь процесс сборки Linux оказывается настолько тесно завязанным именно на bash-скриптинг, что альтернативный выбор выходит себе дороже (не зря же это была одна из первых программ, которую Линус запустил на своем ядре).

Что касается опциональной части Base Linux, то здесь по определению все альтернативно. Начать с наипервейшего пользовательского приложения - текстового редактора: для целей конфигурирования вполне можно ограничится чем-то предельно простым, типа nano. Если же требуется вся мощь системы обработки текста - на очереди будет скорее всего Vim (к тому же - стандарт для всех Unix-систем вообще). Ну, а из промежуточных решений - я лично обеими руками за joe.

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

В итоге мы получаем список чуть более чем в полсотни пакетов, общий объем которых укалывается в сотню мегабайт. Их можно скачать заблаговременно. А можно, поскольку, как я уже сказал, Lonix позволяет настроить подключение к Сети, тянуть и по ходу дела. Возникает вопрос - какие версии? На мой взгляд - самые свежие из стабильных (или самые стабильные из свежих). Правда, в этом случае схема установки LFS Герарда не сработает в полной мере (она довольно жестко привязана к версиям пакетов), и в нетривиальных ситуация придется искать собственное решение, но не это ли - самое интересное?

Так что остается засучить рукава и приступить к работе. Но сначала - важное предупреждение: будьте готовы уделить этому занятию достаточное количество времени. Даже если все пойдет как надо (а по первому разу на такое можно только надеяться, но никак не рассчитывать), сам по себе процесс компиляции займет несколько часов чистого времени на мощной машине. И не говорите, что вас не предупреждали.

А на кой все это?

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

Действительно, существует немалое количество прекрасных пакетных дистрибутивов, на инсталляцию которых в полном объеме нынче (с настройками) уходит меньше времени, чем на установку Windows. Есть и дистрибутивы Source Based, их развертывание требует несколько большего времени, но зато позволяет держать процесс (почти) под полным контролем. Стоит ли тратить время на собирание очередного велосипеда? Да еще и без гарантии (по первому разу, по крайней мере) адекватного затраченным усилиям результата...

Навязывать свое мнение не буду (а мой ответ, как легко догадаться, сугубо положительный). Просто постараюсь перечислить резоны, которые могут подвигнуть на системный самострой.

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

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

Ну и последнее по счету - спортивный интерес. Хотя по значению этот резон я поставил бы на первое место. Ибо без него все остальные просто теряют силу.

Продолжение следует