Знакомьтесь — Linux From Scratch
Вместо вступления
«Хочешь начать изучать GNU/Linux? Начни с Linux From Scratch.»
Единственный бумажный дистрибутив
LFS (здесь и далее аббревиатура от Linux From Scratch) – книга, написанная Герардом Бикмансом, описывающая процесс сборки минимального рабочего варианта GNU/Linux из исходных кодов. Почему бумажный? В свое время книгу можно было купить в твердом переплете, что делает «дистрибутив» несколько необычным, не правда-ли? Помимо самой книги, для сборки конечно-же понадобится интернет (или заранее загруженные исходные коды), свободный раздел на жестком диске, и любая операционная система на базе ядра Linux, имеющая компилятор. Лично я всегда использую либо уже собранный дистрибутив LFS, либо полную установку Slackware – в нем есть все необходимое, чего не скажешь про (например) Ubuntu. Конечно, всегда можно загрузить нехватающие пакеты, но ведь мы хотим только-только научиться линуксу? А Slackware даже в своей базовой установке и без конфигурирования предоставляет требуемый инструментарий.
Следует сказать сразу — дистрибутив собранный по книге LFS не умеет толком ничего. Вернее, ничего такого, что потребуется неискушенному пользователю. Он умеет включаться, выключаться, перезагружаться, использовать Ethernet подключение, но что самое главное — компилировать. Так существуют другие книги, теперь уже поддерживаемые сообществом — Beyond LFS позволяет собрать те самые, интересные пользователю, программы. От браузера и графической среды, до систем управления базами данных и DHCP сервера. Книга имеет свойство отставать в версии от базовой книги, но полученный от LFS опыт обычно достаточен, для самостоятельного разрешения конфликтов версий. Три другие книги — Automated LFS, Cross LFS и Hardened LFS полностью соответствуют названиям и выходят за пределы этой статьи. Впрочем, всегда можно почитать в интернете, правда?
Но почему начинать с него?
Все очень просто, если не сказать — до смешного. Помимо инструкций, в книге много теоретического (но крайне сжатого и как следствие — не заунывного) материала. Установите Ubuntu. Вы знаете что делает пакет Libtool? Или Gawk? После пары успешных сборок LFS, вы будете знать каждый пакет в своей системе и что самое главное — представлять, как они взаимодействуют. Да, состав системы минимальный, но это постоянно подогревает интерес к ее усовершенствованию. Приучит частенько обращаться за помощью к Google и читать англоязычную документацию. Поначалу вы не будете понимать и половины своих действий, внимательно перепечатывая или копируя блоки кода в консоль. Но в самом конце, осознание того, что эту неказистую, без поддержки графики и вашей мощной видеокарты, без новомодного Aero и сенсорных экранов, операционную систему вы собрали сами, придаст вам такой запас сил и гордость, что вы сами потянитесь за новыми знаниями и новыми победами. Я немного утрирую, но ощущения после первой перезагрузки в новую систему сложно забыть даже сейчас.
Цифры и суровая правда жизни
LFS вовсе не минимальный по своему весу дистрибутив. Для сборки потребуется порядка 3 свободный гигабайтов на диске (это помимо уже рабочей Linux-Based системы) — тем не менее, после определенных танцев, систему можно будет превратить в Live-CD. Если у меня будет такая возможность, я расскажу как это делается, в последствии. Компиляция всего и вся (с учетом необходимости создания конфигурационных файлов и прочего) занимает около двух дней. Это если с перерывами на сон, питание и отключение компьютера на ночь. С другой стороны, это зависит от производительности компьютера, на котором собирается система. Моей первой жертвой был ноутбук MSI X-340 — процессор Intel Core 2 Solo с тактовой частотой 1.2 гигагерца (вообще говоря, LFS рекомендуется собирать на одноядерной системе). Оперативная память — 2GB DDR2. Вполне достаточно даже более низких характеристик, а на быстром процессоре сборка пойдет значительно быстрее.
Кстати, приблизительное время сборки каждого из пакетов указано в учебнике. За единицу времени, принимается время сборки пакета Binutils — ассемблера, линкера и ряда других, более мелких утилит для работы с объектными файлами. На вышеуказанной системе это заняло три минуты.
Состав дистрибутива
Перечислять все входящие в LFS пакеты не имеет большого смысла. Список получится длинным, и практически ни о чем не говорящим новичку; избыточным для человека разбирающегося. В этом небольшом разделе я лишь хотел дать несколько общих советов. Во-первых, собирая пакет, не описанный в книге, загляните в репозиторий патчей — возможно его уже адаптировали для использования в LFS. Во-вторых, BLFS почти полностью состоит из опциональных пакетов — просто выбирайте те, которые вам нужны и смело добавляйте в свою сборку LFS. И третье: с самого начала используйте пакетный менеджер. В книге этому уделяется глава, но практические инструкции отсутствуют чуть менее, чем полностью. Я лишь могу порекомендовать Guarded Installation Tool – написанный на Bash’е скрипт, обеспечивающий минимальный набор команд, для управления пакетами, зависимостями и версиями. В LFS этого будет достаточно. В последствии вы можете скомпилировать из исходных кодов APT или DPKG — это неплохо освещено на форумах сообщества.
Вместо заключения
За прошедшие полтора года я сильно продвинулся в своем изучении. Продвинулся со стадии «Есть такая операционная система» до уровня «Подниму сервер под Gentoo за трое суток». Я еще очень далек от идеала и вряд ли могу даже называть себя настоящий линуксоидом — на домашнем компьютере уживаются старенькая Windows XP и Xubuntu 10.10, но знаете что я отвечаю, когда меня спрашивают с чего начать изучать линукс? Начните с Linux From Scratch.
Источник
Делаем из Linux From Scratch свой универсальный дистрибутив
Так уж случилось, что пару лет назад по долгу службы на команду разработчиков, к которой я отношусь, свалилась неожиданная задача — разработка системы управления оборудованием (в этом-то как-раз неожиданности нет, ибо направление разработок такое) с управляющим PC под Linux.
Разработки линуксовой части велись (да и ведутся) под Ubuntu, в среде Code::Blocks. Но, как показала практика, для качественной работы нужно что-то гораздо более легкое с гарантированным временем отклика. Для работы было достаточно консоли, так как задачи организации пользовательского интерфейса решались на подключаемом по TCP/IP удаленном компьютере.
Тогда и пришла идея использовать дистрибутив Linux собственной сборки, чем (сборкой дистрибутива), собственно, в свободное время я и занялся. Выбор пал на LFS. Про то что такое LFS уже неоднократно писали даже на Хабре, я же опишу решение нескольких дополнительных (кроме простенького Linux’а) задач, вставших передо мной в нашем конкретном случае.
Поначалу такая задача была одна — использовать real-time ядро.
Однако дальше, когда идея USB-флешки с дистрибутивом, пришлась всем по душе, то появились задачи размножения флешек и запуска системы на различных компьютерах (тестовых стендов много, имея свою флешку суешь в карман и иди к любому). Вот тут и появились проблемы — LFS не обладает 100% переносимостью с одного компьютера на другой. Для ее адаптации к конкретному компьютеру нужно править некоторые скрипты, что в условиях команды вчерашних Windows-кодеров проблематично (на виртуалку с Ubuntu некоторые пересели, но консоль и скрипты — это беда). Размножение системы также требует повторения некоторых манипуляций, проделываемых в процессе сборки (тот же GRUB установить).
Естественно, решение всех задач есть на просторах интернета, но, думаю, сбор некоторой информации в одном месте никому не помешает.
Итак, конкретные задачи были следующие…
1. Использование ядра Linux с real-time патчем
Это была одна из самых легких задач. Процесс сборки прошел по книге LFS с единственным исключением — вместо штатного для книги ядра было взято 2.6.33.9 и RT-патч для него. Везде, где происходили манипуляции с ядром (установка Linux Headers и ядра непосредственно), работаем с нашей пропатченной версией.
Также не лишним будет сказать, что дистрибутив собирался без подключения swap-раздела (2Гб ОЗУ это в нашем случае — выше крыши, наличие swap не желательно по причине его негативного влияния на гарантированное время отклика, да и для флешки он крайне губителен) и представлял собой один единственный раздел ext2fs.
2. Автоматический вход в систему (в условиях разработки безопасность нам не важна, да и систему пускаем под рутом по ряду причин)
Идея автоматического входа была взята отсюда.
Был создан файл autologin.c следующего содержания:
Далее файл был скомпилирован командой:
gcc autologin.c -o /usr/local/sbin/autologin
Далее было решено, что двух консолей с автоматическим входом хватит (одна для запуска системы, другая для всего остального, если понадобится).
В файле /etc/inittab строчки:
1:2345:respawn:/sbin/agetty tty1 9600
2:2345:respawn:/sbin/agetty tty2 9600
были заменены на:
1:2345:respawn:/sbin/agetty -n -l /usr/local/sbin/autologin tty1 9600
2:2345:respawn:/sbin/agetty -n -l /usr/local/sbin/autologin tty2 9600
После этого никаких проблем с автоматическим входом не было, поэтому никаких дополнительных манипуляций со скриптами не было.
3. Отвязывание системы от порядка подключения дисков
У разных BIOS свои заморочки. Одни, например, считают, что первым является тот диск, с которого мы загружаемся. В этом случае наша флешка будет sda. Другие считают, что сначала должны идти жесткие диски, а потом другие устройства. В этом случае наша флешка будет иметь имя sdb, sdc и так далее.
В результате, то система не может загрузиться с диска, которого нет, то корневой каталог не может быть смонтирован по той причине, что в /etc/fstab указан не тот диск.
Все решается либо исправлением /boot/grub/grub.cfg и /etc/fstab под конкретную машину или использованием для загрузки и монтирования не имени диска (sda, sdb и т. д.), а UUID файловой системы, который для данной файловой системы на флешке будет уникален и, что самое главное — постоянен.
Проблема в том, что GRUB работать с UUID умеет, а ядро — нет, то есть напрямую монтировать корневую систему по UUID (не зная имени устройства) невозможно. Это не баг, а следствие идейных соображений Линуса Торвальдса, поэтому на такую возможность и в будущем надеяться не стоит. Тем не менее пути обхода есть — это initramfs.
Initramfs — временная файловая система, помогающая в загрузке и монтировании файловых систем настоящей системы.
В стандартную сборку LFS initramfs не входит, поэтому для ее построения воспользуемся рекомендациями из Gentoo Wiki и некоторыми собственными соображениями (вариант из Gentoo Wiki без изменений в моем случае проблему с именами дисков не решил, да и не заработал толком).
Для создания простейшей initramfs системы, монтирующей нашу основную по UUID нужна простейшая командная оболочка (shell) и скрипт init. Полный набор утилит командной строки достаточно громоздок для initramfs, поэтому часто для этой цели применяется busybox, который при скромных размерах и требованиях реализует некоторые, наиболее часто используемые утилиты.
Забираем последнюю версию busybox:
Распаковываем и конфигурируем:
tar jxf busybox-1.18.4.tar.bz2
cd busybox-1.18.4
make menuconfig
Конфигурирование производится при помощи меню (наподобие ядра Linux). В принципе, стандартной конфигурации хватает для наших нужд, но, на всякий случай, стоит проверить, что подключены следующие возможности:
Support for devfs — поддержка devfs для работы с /dev.
Build Busybox as a static library (no shared libraries) — статическая компоновка, чтобы не тянуть за собой кучу so-библиотек.
Support version 2.6.x Linux kernels — поддержка ядер линейки 2.6.
А также поддержка функциональности утилит: sh, cat, cut, findfs, mount, umount, sleep, echo, switch_root.
Теперь собираем дерево каталогов нашей файловой системы:
mkdir /usr/src/initramfs
cd /usr/src/initramfs
mkdir -p bin lib dev etc mnt/root proc root sbin sys
cp -a /dev/
Копируем busybox и создаем линки на утилиты:
cp /sources/busybox-1.18.4/busybox ./bin/
cd bin
ln -s busybox sh
ln -s busybox cat
ln -s busybox cut
ln -s busybox findfs
ln -s busybox mount
ln -s busybox umount
ln -s busybox sleep
ln -s busybox switch_root
cd ..
Осталось написать скрипт init:
Делаем наш скрипт исполняемым:
chmod +x /usr/src/initramfs/init
Собираем нашу временную файловую систему в архив:
cd /usr/src/initramfs
find . -print0 | cpio —null -ov —format=newc | gzip -9 > /boot/initrd.img-2.6.33-rt31
Обратим внимание на имя файла — оно должно соответствовать имени ядра (это нужно, чтобы GRUB его правильно подцепил). То есть, если ядро имеет имя vmlinux-2.6.33-rt31, то initramfs должен иметь имя initrd.img-2.6.33-rt31.
Теперь при выполнении grub-mkconfig GRUB обнаружит initramfs, а также включит в конфигурацию UUID корневой системы. Для проверки можно поправить /boot/grub/grub.cfg руками. Например конфигурацию:
menuentry «Linux 2.6.33-rt31» —class gnu-linux —class gnu —class os <
insmod ext2
set root='(hd0,1)’
search —no-floppy —fs-uuid —set 47029df8-8567-417d-b813-eedfe1ff8b0f
linux /boot/vmlinux-2.6.33-rt31 root=/dev/sda1 ro
>
menuentry «Linux 2.6.33-rt31» —class gnu-linux —class gnu —class os <
insmod ext2
set root='(hd0,1)’
search —no-floppy —fs-uuid —set 47029df8-8567-417d-b813-eedfe1ff8b0f
linux /boot/vmlinux-2.6.33-rt31 root=UUID=47029df8-8567-417d-b813-eedfe1ff8b0f ro
initrd /boot/initrd.img-2.6.33-rt31
>
UUID файловой системы можно узнать так (например, для /dev/sdb1):
blkid -p -o udev /dev/sdb1
Осталось поправить /etc/fstab, заменив строчку:
/dev/sda1 / ext2 defaults 1 1
UUID= 47029df8-8567-417d-b813-eedfe1ff8b0f / ext2 defaults 1 1
Также следует заметить, что для всех манипуляций выше необходимо, чтобы в ядре была включена поддержка devtmpfs (CONFIG_DEVTMPFS=y) и initramfs (CONFIG_BLK_DEV_INITRD=y).
4. Отвязывание системы от сетевой карты
Если в компьютере установлено более одной сетевой платы, то при параллельной загрузке модулей ядра не гарантируется постоянное назначение имен этим платам. Например, есть две платы. Плата_1 имеет имя интерфейса в системе eth0, Плата_2 — eth1. При очередной перезагрузке может получиться так, что Плата_1 станет eth1, а Плата_2 — eth0.
С этой целью в LFS производится привязка имени к конкретной плате. При загрузке на другом компьютере очень велика вероятность, что сеть не поднимется.
В моем конкретном случае плата на всех компьютерах одна и IP — статический (связь только с терминальным компьютером напрямую).
Поднятие сетевого интерфейса в LFS осуществляется скриптом /etc/rc.d/init.d/network. Допишем скрипт так, чтобы каждый раз при загрузке генерировался конфигурационный файл /etc/udev/rules.d/70-persistent-net.rules и при завершении работы этот файл удалялся. Подозреваю, что есть метод проще, но найденный метод заработал, а копаться в принципах работы Udev времени и особого желания на момент сборки системы не было.
В начало раздела start команды case добавляем:
А в конец секции stop (непосредственно перед ;;) добавляем:
Теперь при загрузке на любой системе имя сетевого интерфейса будет eth0 (кроме самых экзотических случаев) и сеть будет подниматься. Разумеется, каталог /etc/sysconfig/network-devices/ifconfig.eth0 с файлом ipv4 должен существовать. Содержимое этого файла описано в книге LFS.
5. Написание скрипта, производящего инсталляцию LFS на любую флешку
Осталось последнее — сделать архив системы и скрипт, который будет ее устанавливать на произвольный носитель.
Загружаемся в другой системе (не с флешки), монтируем флешку, например в /mnt/usb-os. Архивируем содержимое:
cd /mnt/usb-os
tar -cvjf
Пишем скрипт для установки install_usb-os.sh. В качестве параметра скрипт принимает имя устройства, на котором необходимо развернуть систему (например /dev/sdb). Скрипт сам создаст необходимый раздел и файловую систему (/dev/sdb1, если указано имя /dev/sdb), распакует архив и установит GRUB.
Запускаться он должен с правами root и, на самом деле, очень опасен.
В случае неверного указания имени устройства могут быть уничтожены все данные на рабочем диске!
Источник