Собираем ядро и мир FreeBSD из исходников
29 марта 2016
Сегодня мы научимся собирать ядро и мир (основные исполняемые файлы, библиотеки и тд) FreeBSD из сходных кодов. Ранее в заметке PostgreSQL: сборка из исходников и настройка под Linux мы выясняли, зачем нужно уметь собирать что-то из исходников. Основными сценариями являются оптимизация под конкретное железо и получение самого свежака прямо из ветки master. Кроме того, вы можете настроить ядро под свои конкретные нужды — выбрать шедулер, отключить IPv6, убрать поддержку лишнего железа и тд. Наконец, если вдруг вы планируете когла-нибудь стать коммитером в ядро FreeBSD, знания о том, как это ядро собирается, будут не лишними.
Дисклеймер: Многое из написанного ниже может потерять актуальность к моменту, когда вы будете это читать. Прежде, чем действовать по приведенной инструкции, не лишним будет сначала свериться с хэндбуком. Заметьте также, что ниже речь идет исключительно про сборку ядра и мира из исходников, а процедура бинарного обновления системы описана в заметке Памятка по обновлению ядра и мира FreeBSD.
Подготовка окружения
При написании заметки я использовал следующий установочный диск:
Лишней железки под рукой у меня не было, поэтому все эксперименты ставились на VirtualBox. Был выбран VirtualBox, а не Vagrant, так как нам понадобится доступ к монитору системы. В VirtualBox в настройках сети было создана два адаптера — один NAT и один Host Only. Первый нужен для доступа гостевой системы в интернет. Второй позволит ходить в гостевую систему с хост-системы по SSH.
После установки системы ставим пакеты git-lite, vim-lite, tree, bash, sudo, правим /usr/local/etc/sudoers, затем меняем оболочку пользователя:
В ~/.gitconfig дописываем:
pager = less -S
Мне лично еще очень нравится иметь в системе привычный htop:
sudo portsnap fetch extract
cd sysutils/htop
sudo make -DBATCH install clean
Подробности про первоначальную настройку системы и управление пакетами во FreeBSD вы найдете в заметках Использование FreeBSD на десктопе, версия 2.0 и Управление пакетами во FreeBSD при помощи утилиты pkg соответственно.
Собираем ядро
То, как будет собираться ядро FreeBSD, контролируется несколькими файлами конфигурации.
Часть настроек лежит в /etc/make.conf. Этот файл влияет на сборку портов, мира, ядра FreeBSD, и вообще любых программ на C. Здесь можно указать CPU, под который производится сборка, флаги оптимизации, и так далее. Перечень всех доступных опций можно подглядеть в /usr/share/examples/etc/make.conf и man make.conf. Пример /etc/make.conf:
CC=/usr/local/bin/clang37
CXX=/usr/local/bin/clang++37
CPP=/usr/local/bin/clang-cpp37
# оптимизируем код под используемый на машине CPU
CPUTYPE?=native
# флаги при компиляции кода на C и C++
CFLAGS+=-O2 -pipe
CXXFLAGS+=-O2 -pipe
Еще есть /etc/src.conf, который имеет немного другие настройки и затрагивает только ядро и мир. Подробности смотри в man src.conf. Пример /etc/src.conf:
CFLAGS+=-O2 -pipe
COPTFLAGS+=-O2 -pipe
Наконец, также существует и файл конфигурации самого ядра. Про него будет рассказано далее.
Если при установке FreeBSD вы поставили галочку «установить все исходники», то исходники ядра и мира будут находится в каталоге /usr/src. Информацию о том, что в каком подкаталоге находится, можно найти в Developer’s Handbook и файле README.
Забыли поставить галочку? Не расстраивайтесь. Все равно вам, скорее всего, хотелось бы иметь самые свежие исходники, а не те, что были записаны на установочный CD. Исходники FreeBSD можно скачать с официального SVN-репозитория, а также с его зеркала на GitHub.
Мне лично Git ближе и милее, поэтому я сделал следующее:
sudo mkdir src.backup
sudo mv src/* src.backup
sudo git clone https://github.com/freebsd/freebsd.git src
cd src
Выбираем ветку. Я лично выбрал master.
Если же вы все-таки предпочитаете Subversion:
cd /usr/src && sudo svn co http://svn.freebsd.org/base/head/ ./
Настройки, с которыми собирается ядро, лежат в файле:
Название архитектуры зависит от вашего CPU. Как правило, это либо i386, либо amd64. Конфиг ядра, идущего в системе по умолчанию, называется GENERIC. Можно скопировать его и назвать, например, MYKERNEL.
sudo cp GENERIC MYKERNEL
Конфиг хорошо документирован. К примеру, можно отключить поддержку IPv6 и IPSec, закомментировав две строчки:
#options IPSEC
Важно! В CURRENT по умолчанию включен механизм witness, предназначенный для поиска дэдлоков. Имейте в виду, что он может выводить в консоль пугающие стэктрейсы, некоторые из которых являются багами и должны быть зарепорчены в рассылку freebsd-current@, а некоторые являются вполне безобидными. Также сообщается, что механизм этот довольно тормозной, и потому вам вполне может захотеться его отключить.
Собираем ядро с нашими настройками:
sudo make -j4 buildkernel KERNCONF=MYKERNEL
Перед установкой ядра делаем резервную копию текущего:
При установке нового ядра резервная копия создается автоматически, но эта копия будет затерта при следующей установке. После создания резервной копии вручную у нас под рукой всегда будет 100% рабочий GENERIC, с которого можно будет загрузиться в случае возникновения проблем.
Устанавливаем новое ядро:
После установки ядро окажется в каталоге /boot/kernel, а резервная копия текущего ядра будет лежать в /boot/kernel.old.
Вместо пары шагов buildkernel и installkernel также можно было использовать команды:
sudo nextboot -k kernel.test
Этим мы сказали положить ядро в /boot/kernel.test и использовать его один раз при следующей закрузке. Если все пройдет хорошо, после перезагрузки /boot/kernel.test можно будет переименовать в /boot/kernel. Этот вариант может быть удобнее, если к машине нет физического доступа.
Перезагружаемся:
После загрузки системы проверяем версию ядра:
Должны увидеть что-то вроде
Feb 28 13:40:05 MSK 2016 root@vbox:/usr/obj/usr/src/sys/MYKERNEL amd64
Если что-то пошло не так, при загрузке системы в меню можно выбрать загрузку с kernel.old (нажатием цифры 5). Также можно выбрать «Escape to a loader prompt» (нажатием цифры 3) и выбрать вообще любое ядро, например:
Таким образом, даже если мы вдруг запорим ядро, есть запасной парашют.
Собираем мир
Мир от FreeBSD 10 почти наверняка будет не лучшим образом работать с ядром FreeBSD 11. Поэтому не лишено смысла вместе с пересборкой ядра системы обновить сразу и мир.
Важно! Компиляция мира может занять очень много времени, особенно если в VirtualBox вы дали виртуалке только одно ядро. Если вы используете реальную машину, вам потребуется физический доступ к ней. Также от вас потребуется вручную смержить множество конфигов, подтвердить удаление множества файлов, а потом (!) переустановить все установленные пакеты и пересобрать все установленные порты. Возможно, вместо сборки нового мира, вам будет проще временно вывести машину из эксплуатации, поставить на нее новую систему, и настроить поверх все необходимое. Или воспользоваться уже упомянутым механизмом бинарного обновления. Как мне кажется, пересборка мира — процедура больше для разработчиков FreeBSD, чем администраторов боевых серверов.
Итак, переходим в каталог с исходниками:
Чистим временные файлы, которые могли остаться с предыдущей сборки:
Собираем мир:
Чтобы минимизировать риски, связанные с обновлением уже запущенных и работающих приложений, рекомендуется перевести ОС в однопользовательский режим:
sudo shutdown now
Теперь монтируем файловую систему (у меня ZFS):
zfs mount -a
Если вы используете UFS, тогда:
mount -a -t ufs
swapon -a
Перед установкой нового мира может потребоваться подготовить файлы конфигурации, создать новые группы, и так далее. Делается это командой:
Там довольно простой диалоговый режим, ничего особенного.
Ставим новый мир:
make installworld
Завершаем правку конфигов и вот это все:
Удаляем файлы, ставшие ненужными:
Перезагружаемся:
После перезагрузки, согласно хэндбуку, также нужно обновить установленные пакеты:
Если что-то ставили из портов, то их тоже придется пересобрать:
sudo portsnap fetch update
sudo pkg install portmaster
sudo portmaster -af
После чего можно удалить библиотеки, ставшие теперь ненужными:
sudo make delete-old-libs
Вот так хитро во FreeBSD происходит пересборка мира.
Запуск тестов
Начиная с FreeBSD 11 мир включает в себя набор тестов. Запускаются эти тесты таким образом:
sudo kyua test -k /usr/tests/Kyuafile
sudo kyua report
Тесты запускаются под sudo, так как некоторые из них требуют рутовых прав. Без sudo такие тесты будут пропущены. Некоторые тесты выполняются очень долго (скажем, 80 секунд), а всего тестов более 3.5 тысяч, так что будьте терпеливы.
Заключение
Как видите, процесс компиляции ядра и мира FreeBSD из исходных кодов не является самым простым, но разобраться в нем вполне реально. К счастью, во FreeBSD есть превосходная документация практически на все. Поэтому, если в этой заметке вы не нашли чего-то, что вы искали, обращайтесь к хэндубку!
Дополнение: Также вас могут заинтересовать статьи Памятка по отладке ядра и драйверов во FreeBSD и Памятка по сборке ядра Linux из исходного кода.
Вы можете прислать свой комментарий мне на почту, или воспользоваться комментариями в Telegram-группе.