И снова здравствуйте, уважаемые любители ядерной физики. Сегодняшний материал - четвертый из серии о принципах создания живых дистрибутивов. Но если предыдущие были больше похожи на теоретические лекции, то этот - на лабораторную работу. В нем я намереваюсь дать пошаговое руководство по созданию живого дистрибутива произвольной конфигурации, подробно объясняя что происходит.
Сразу оговорюсь, что не буду повторно рассказывать о том, что изложено ранее. Это даст возможность сконцентрироваться на понимании сути технологии. Так что ответы на возникающие по ходу чтения вопросы можно найти в моих предыдущих статьях, а также в руководстве Люка Парсона "Creating your own Linux Live CD", которое я хоть и покритиковал, но которое содержит исходную информацию для построения живого дистрибутива.
Однако приступим. "Живой дистрибутив" мы будем создавать на основе Slackware 12.0, поскольку его быстрее и проще установить в минимальной конфигурации на виртуальную машину. Ах, да, конечно же: все работы мы будем проводить под виртуальной машиной, в качестве каковой я выбрал VirtualBox (потрясающе адекватная вещь!).
Итак, используя виртуальную машину, создаем виртуальный жесткий диск объемом гигабайта 2 (а лучше больше), устанавливаем все пакеты из директорий /slackware/a/(базовые пакеты), /slackware/d/ (инструменты разработчика). Из /slackware/ap устанавливаем Midnight Commander (без него будет тяжеловато лазить по деревьям), из /slackware/l - библиотеку ncurses (без нее не заработает mc). Можно было бы еще установить исходники ядра (/slackware/k), но ядро мы возьмем посвежее - 2.6.23, поскольку в этом случае будет меньше мороки с модулями.
Свежее ядро можно взять с диска к журналу "Хакер". Журнал стоит 150 рублей, и 8-гигабайтный диск, на котором можно найти самые свежие версии большинства популярных программ как под Win, так и под *nix, этих денег стоит.
Распаковываем в /usr/src следующие вещи:
1) Исходники ядра 2.6.23;
2) Комплект исходников aufs.
3) Комплект исходников squashfs.
Где и как скачать aufs и squashfs см. в руководстве Люка Парсона. Однако ни в коем случае не следуйте его рекомендациям по установке патчей и компилированию ядра! Там много лишнего и не всегда срабатывающего. Например, механизм lzma, которым предлагается пропатчить squashfs может и дает преимущества в степени компрессии, но процесс изготовления ядра весьма затемняет и усложняет. В моих предыдущих статьях написано, как с минимальными затратами времени и нервов изменить исходники ядра, чтобы оно стало поддерживать aufs и squashfs. Если что-то не понятно - пишите каменты, поясню. Скажу только, что когда у вас дело дойдет до make menuconfig, в меню должны быть видны соответствующие позиции в разделе File Systems (и его подразделах): Another Unionfs и Squashfs 3.3. Эти возможности можно скомпилировать в виде модулей, но я настоятельно рекомендую включить их в тело ядра, пометив звездочкой, а не буквой М.
Прежде чем выполнить make clean && make bzImage, мы подготовим к включению в наше ядро еще одну вещь - initramfs. Как я уже писал, initramfs - это cpio-архив, сжатый gzip'ом (язык не поворачивается сказать "зазипованный", ибо zip и gzip, все-таки, немножко разные вещи). Почему архив cpio, а не tar - Бог весть, хозяин - барин. Создаем каталог /tmp/initramfs, распаковываем туда содержимое файла initrd.img, входящего в дистрибутив Slackware, указываем в make menuconfig путь к initramfs (подробности см. в предыдущей статье).
Ну вот, подготовительные операции завершены. Можно сделать make clean && make bzImage, скопировать получившееся ядро в /boot, подправить /etc/lilo.conf и не забыть ввести команду lilo, чтобы новое ядро можно было выбрать при загрузке. В меню lilo должно теперь быть два пункта: первый - изначально там существовавший (пометим его как Laboratory) и второй - для входа под вновьскомпилированным ядром (пометим его как Testing).
Обратите внимание на то, какое жирненькое получилось ядрышко: мегабайт, чай, 5 с хвостиком. Это потому, что в него включена начальная файловая система, копия которой лежит в каталоге /tmp/initramfs. Если есть желание - можете там что-нибудь подправить, прежде чем компилировать ядро. Например, убрать дурацкие вопросы в etc/rc.d/rc.S (о выборе языка, который один хрен не выбирается и о вводе пароля root, который просто считывается в пустоту). Обана! Чуть не забыл: прежде, чем компилировать ядро, в каталог /tmp/initramfs/bin нужно скопировать утилиту mksquashfs. Ее, в свою очередь, можно скомпилировать, выполнив make в каталоге /usr/src/squash3.3/utils (ну, или примерно так).
Скомпилировав ядро, давайте выключим пока нашу виртуальную машину командой halt и добавим к ней еще один виртуальный жесткий диск (primary slave) объемом в 1 Гб. Он понадобится нам для подготовки нашего Live CD. И вот еще что: нужно зашарить какую-нибудь папку "большой" машины, например /tmp, чтобы она была видна из виртуальной машины. Для этого в VirtualBox, например, используйте опцию "Общие папки" (подробности см. в одной из предыдущих статей и в документации по VirtualBox). В нее мы будем сбрасывать файлы, необходимые для создания нашего Live CD.
Настал момент загрузиться с нового ядра. Оно у нас получилось самодостаточным. Ему не нужны ни жесткий диск, ни initrd.img, ни сеть, потому что внутри него зашит скромный, но вполне полноценный набор утилит. По окончании загрузки вы можете, например, создавать каталоги, копировать файлы, поправить что-то редактором vi, разметить жесткий диск. Вот этим и займемся: на гигабайтном /dev/hdb создадим 4 раздела 100, 200, 200 и 400 Мб. На каждом создадим файловую систему ext2 или ext3 (а можно и reiserfs). Теперь немножко помонтируем. Создаем каталоги /mnt/hdb1, /mnt/hdb2, /mnt/hdb3, /mnt/hd4. Монтируем в каждый из них соответствующие разделы и копируем: в /mnt/hdb1 - содержимое /bin, в /mnt/hdb2 - содержимое /lib, в /mnt/hdb3 - содержимое /sbin, и на самый объемный - /mnt/hdb4 - содержимое /usr. Например:
cp -av /bin/* /mnt/hdb1
Теперь отмонтируем все 4 раздела и монтируем их в соответствующие каталоги:
umount /dev/hdb1
umount /dev/hdb2
umount /dev/hdb3
umount /dev/hdb4
mount /dev/hdb1 /bin
mount /dev/hdb2 /lib
mount /dev/hdb3 /sbin
mount /dev/hdb4 /usr
Ход мысли понятен? Так точно, сейчас мы будем устанавливать систему в желаемой конфигурации и нам нужно будет интенсивно звписывать в эти 4 основных каталога. Файлы будут попадать и в каталог /etc, но наша initramfs вполне способна принять небольшой объем информации, так что к /etc монтировать ничего не будем. Ну вот, пришла пора установить необходимые пакеты. Монтируем диск с дистрибутивом Slackware:
mkdir /mnt/dvd
mount -t iso9660 /mnt/cdrom /mnt/dvd
Далее - стандартно устанавливаем необходимые пакеты с помощью утилиты installpkg. Не знаю, какие пакеты вам нужны, но абсолютно точно нужно сделать
installpkg /mnt/dvd/slackware/a/*.tgz
то есть установить базовые пакеты.
Ну вот, у нас получилась вполне работоспособная система, которую можно даже поэксплуатировать до перезагрузки. Но у нас другие цели. Пришла пора заняться нашим CD. Его мы будем собирать в файловом пространстве "большой", т.е. не виртуальной, а реальной машины. Для этого зашарим каталог /tmp большой машины в каталог /mnt/tmp виртуальной машины:
mkdir /mnt/tmp
mount -t vboxsf tmp /mnt/tmp
mkdir /mnt/tmp/iso_result
Теперь у нас достаточно места для создания ISO-образа. Давайте уже сбросим сжатые "кусочки" нашего будущего Live CD в эту большую папку:
cd /bin
mksquashfs . /mnt/tmp/iso_result/bin.squash
cd /etc
mksquashfs . /mnt/tmp/iso_result/etc.squash
cd /lib
mksquashfs . /mnt/tmp/iso_result/lib.squash
cd /root
mksquashfs . /mnt/tmp/iso_result/root.squash
cd /sbin
mksquashfs . /mnt/tmp/iso_result/sbin.squash
cd /usr
mksquashfs . /mnt/tmp/iso_result/usr.squash
Думаю, смысл происходящего ясен: в файлы с расширением .squash мы записывеам сжатые образы соответствующих каталогов, которые в нашем Live CD будут примонтированы в соответствующие точки благодаря тому, что наше ядро скомпилировано с поддержкой squashfs.
Перезагрузим вновь нашу виртуальную машину, выбрав из меню lilo пункт Laboratory, то есть загрузившись не под нашим новым большим ядром, а под старым, установленным системой: нам нужно внести кое-какие изменения в файл /tmp/initramfs/etc/rc.d/rc.S. Именно этот скрипт отвечает за то, что происходит во время загрузки начальной файловой системы. Ему мы и поручим смонтировать наши размещенные на CD-ROM squash-кусочки в нужные каталоги. Дописываем в конец rc.S:
mount -i iso9660 /dev/cdrom /mnt/cdrom
mount -t squashfs -o loop /mnt/cdrom/bin.squash /bin
mount -t squashfs -o loop /mnt/cdrom/lib.squash /lib
mount -t squashfs -o loop /mnt/cdrom/sbin.squash /sbin
mount -t squashfs -o loop /mnt/cdrom/usr.squash /usr
(проверьте, есть ли в каталоге /tmp/initramfs точка монтирования mnt/cdrom).
Понятно, что поисходит? К куцей начальной файловой системе, загруженной прямо из ядра через механизм initramfs, мы добавляем ветви, содержащие полноценные библиотеки и программы, превращая минимальный набор утилит в полноценную ОС. Но вот беда: squashfs может работать только в режиме чтения. На нее, как на CD-ROM, ничего нельзя записать. А записывать надо. Не говоря уже о том, что в каталоге /root хотелось бы творить что-нибудь специфическое, каталог /etc должен быть доступен для записи уже в момент загрузки: система пишет в него файл mtab при монтировании устройств. И тут на сцену выходит aufs. Напомню, что эта файловая система предназначена для того, чтобы делать ro-файлы и каталоги "как бы записываемыми". Она лепит "бутерброд" из ro и rw каталогов. В качестве записываемого слоя подойдет, например, жесткий диск. Но мы создаем Live CD, который должен работать и без жесткого диска, поэтому создадим из машинной памяти временную файловую систему, на которую вполне можно вести запись. 3 метра для записи в /etc и 30 для /root будет вполне достаточно. Дописываем в rc.S:
# mount -t squashfs -o loop /mnt/cdrom/etc.squash /etc - это не верно, нельзя писать в такой каталог!
# mount -t squashfs -o loop /mnt/cdrom/root.squash /root - это не верно, нельзя писать в такой каталог!
mkdir /mnt/tmp1
mkdir /mnt/tmp2
mount -t tmpfs -o size=3M tmpfs /mnt/tmp1
mount -t aufs -o dirs=/mnt/tmp1:/mnt/cdrom/etc.squash=ro none /etc
mount -t tmpfs -o size=30M tmpfs /mnt/tmp2
mount -t aufs -o dirs=/mnt/tmp2:/mnt/cdrom/root.squash=ro none /root
Вот так мы победили сырость! Теперь можно записывать в /etc и /root. Конечно, всё записанное хранится лишь в оперативной памяти до ближайшей перезагрузки, но иногда большего и не надо.
Внеся изменения в /tmp/initramfs/etc/rc.d/rc.S, мы изменили initramfs и нам нужно внести ее новый вариант в тело ядра, т.е. перекомпилировать его. Заходим в /usr/src/linux-2.6.23, выполняем make clean && make bzImage. Теперь нам нужно сделать так, чтобы с нашего ядра грузился CD-ROM. Файлы, которые должны быть записаны на него, хранятся не в виртуальной, а в реальной машине, поэтому, чтобы их увидеть из нашей "Лаборатории", монтируем зашаренную папку:
mkdir /mnt/tmp
mount -t vboxsf tmp /mnt/tmp
cd /mnt/tmp/iso_result
В каталоге iso_result нас поджидают несколько файлов с расширением .squash.
Монтируем диск с дистрибутивом Slackware. Копируем из него каталог isolinux/, в котором лежат файлы, ответственные за загрузку системы, в каталог /mnt/tmp/iso_result. Удаляем из /mnt/tmp/iso_result/isolinux всё, кроме isolinux.boot, isolinux.bin. Копируем наше ядро - файл bzImage (лежит в /usr/src/linux/arch/i386/boot), - в /mnt/tmp/iso_result/isolinux. Создаем там же пустой файл isolinux.cfg с помощью команды touch. Пишем в него:
default bzImage
prompt 0
label bzImage
kernel /isolinux/bzImage
Теперь можно жжнуть iso-образ:
cd /mnt/tmp/iso_result
mkisofs -o ../result.iso \
-R -J -A "Yo!" \
-hide-rr-moved \
-v -d -N \
-b isolinux/isolinux.bin -c isolinux/boot.cat \
-no-emul-boot -boot-load-size 32 -boot-info-table \
.
Чтобы каждый раз не вводить это, рекомендую создать в каталоге /mnt/tmp/iso_result соответствующий Makefile и просто делать make.
В результате всей этой работы в каталоге /tmp "большой" (не виртуальной) машины должен появиться файл result.iso. Загрузите с него виртуальную машину и, если всё сделано по уму, вы получите искомый результат. Конечно, для того, чтобы получить настроенную под конкретную задачу систему нужно еще очень много потрудиться, но тут уж... дорогу осилит идущий.





Отправить комментарий