пятница, 1 октября 2010 г.

Пересборка "мира" FreeBSD (памятка)

Решил написать маленькую заметку (памятку) по пересборке "мира" во FreeBSD,
т.к. данная операция выполняется не так часто..
Рассмотрим на примере FreeBSD 8.1.
Приступим...

Обновление исходников

Csup - это клиент для подключения к CVS репозиторию и скачи от туда всякого-разного.
На данный момент проект FreeBSD хранит в CVS зеркалах дерево исходных кодов системы, дерево портов и документацию.
На сегодняшний день этот инструмент уже не является жизненно необходимым в большинстве случаев - дерево портов очень удобно синхронизировать через portsnap, а ставить заплатки на систему можно без пересборки из исходников используя для этого бинарные патчи freebsd-update.
Если же хочеться заниматься пересборкой мира и ядра, то придется научиться обновлять исходные тексты из репозитория.

Для работы csup требуется составить supfile с инструкциями где указываетя - что именно и откуда csup должен скачать, куда и как сохранить.
Пример supfile

#cat /etc/supfile 
# 
# IMPORTANT: Change the next line to use one of the CVSup mirror sites 
# listed at http://www.freebsd.org/doc/handbook/mirrors.html. 
#*default host=cvsup.ru.FreeBSD.org 
*default host=cvsup6.ua.freebsd.org
*default base=/var/db *default prefix=/usr 

#*default release=cvs tag=RELENG_8_1_0_RELEASE 
*default release=cvs tag=RELENG_8 
*default delete use-rel-suffix 
*default compress 
src-all 
# ports-all tag=. 
doc-all tag=. 

Описание директив:
*default host=cvsup.lv.freebsd.org
Так указывается cvsup сервер с которого мы будем скачивать данные. Список с зеркалами можно посмотреть тут (http://www.freebsd.org/doc/handbook/cvsup.html#CVSUP-MIRRORS).
Соответственно имеет смысл указывать тот кто ближе географически (Наиболее близкий сервак можно определить утилитой fastest_cvsup -c ua).

*default base=/var/db
Где csup будет хранить временные и служебные файлы генерируемые в ходе работы. Там будут сохраняться checkouts файлы для каждой из указанных коллекций (src-all, ports-all, doc-all, etc).

*default prefix=/usr
Корень под которым у нас будут сохраняться полученные с сервера данные. В нашем случае это будет /usr/src и /usr/doc. Если указать что-то другое, например /tmp/test то скаченные исходники пойдут туда.

*default release=cvs tag=RELENG_8
Используемый по-умолчанию tag. То есть, если бы его небыло, нам надо было бы вручную указывать что мы хотим скачать. В настройках коллекции src-all ничего не указано - значит она будет использовать тег по-умолчанию какой мы задали, а для doc-all мы тег изменили на tag=. так как коллекция документов не имеет такого же тега как коллекция исходников.

src-all
Перечисляем коллекции которые хотим скачать.

Про теги:
Детальнее про используемые существующие в данный момент теги можно прочитать здесь (http://www.freebsd.org/doc/en/books/handbook/cvs-tags.html) - хендбук всегда в актуальном состоянии.
Что такое тег? В ходе разработки FreeBSD дерево исходных кодов переодически дробится на релизы и на ветки STABLE и CURRENT. Тег указывает какую версию мы хотим скачать.

Вот примеры тегов для дерева src-all:
RELENG_8 - Ветка FreeBSD 8-STABLE
RELENG_8_1 - Ветка FreeBSD 8.1 в которую идут патчи безопасности
RELENG_8_1_0_RELEASE - "Замороженный" снепшот состояния кода FreeBSD 8.1 в момент его релиза
Примечание: посмотреть список releng и их состояние можно на офф. сайте

Для дерева doc-all и ports-all веток типа STABLE не существует, а есть только ветка "." (CURRENT) и замороженные ветки релизов типа RELEASE_8_1_0_RELEASE. Да, тут есть одни грабельки - имена веток релизов для src-all и для doc-all/ports-all отличаются - RELENG/RELEASE!

Пример обновления:
Предположим, что мы поставили себе свежеиспеченую FreeBSD 8.1-RELEASE, и захотели обновить ее до ветки FreeBSD 8-STABLE (или до того же релиза, но с патчами RELENG_8_1). В ходе установки системы мы в sysinstall выбрали, что хотим кроме прочего так же установить и дерево исходных текстов.

Нам необходимо произвести синхронизацию тех исходных текстов которые у нас есть на диске, с репозиторем - скачать новые части.

Последовательность действий такова:
- составляем supfile и сохраняем его где нам больше нравиться. Я обычно сохраняю его в /etc/supfile
- проводим первую синхронизация с замороженной веткой нашего релиза RELENG_8_1_0_RELEASE
- переименовываем checkouts файлы с RELENG_8_1_0_RELEASE на RELENG_8
- проводим вторую синхронизацию с веткой RELENG_8 - обновляем исходники до STABLE
- далее как обычно пересобираем и устанавливаем мир и ядро
- каждый следующий раз, обновляясь до STABLE, делаем это один раз как обычно без переименований файлов

У бывалых БСДшников может возникнуть вопрос - что это еще за чехарда с переименовываением файлов и синхронизацией два раза? Это такой трюк позволяющий во-первых сохранить пропускную способность линии, а во-вторых более чисто провести синхронизацию исходников, чтобы не осталось никаких лишних файлов в дереве. Подробнее эта фишка описана в FAQ на CVSup (http://www.cvsup.org/faq.html#adopt).
Суть идеи в следующем - при работе csup она использует checkouts файлы для того чтобы сравнивать информацию о версиях файлов на локальном диске и на сервере, и проводить синхронизацию только изменившихся. Сразу после установки системы, в директории /var/db/sup никаких checkouts файлов для синхронизируемых нами коллекций еще нет.
Трюк в том, чтобы сначала их создать. Так как у нас релиз 8.1 и исходники установлены от него же, то проведя первую "синхронизацию" с "замороженным" тегом этого же самого релиза RELENG_8_1_0_RELEASE мы сможем построить актуальные checkouts файлы.
Первая синхронизация по сути нечего не синхронизирует, а только энумерует файлы на диске и в репозитории, да строит базу данных - checkouts файл.
После первой синхронизации мы получим в директории /var/db/sup две новых поддиректории doc-all src-all. Первая нас не интересует, а во второй будет файл с именем checkouts.cvs:RELENG_8_1_0_RELEASE.
Этот файл надо переименовать в checkouts.cvs:RELENG_8.
После этого в /etc/supfile заменить ранее использованный тег RELENG_8_1_0_RELEASE на тег для ветки на которую мы хотим обновиться - RELENG_8.
Все, теперь у нас есть актуальные checkouts файлы которые отражают положение вещей на нашем локальном диске. Как только мы начнем вторую синхронизацию с сервером, то csup будет точно знать какие версии файлов надо передать, а что надо удалить.
Синхронизация будет выполнена более чисто, займет меньше времени и потребует меньше трафика.
Как я уже сказал - все последующие синхронизации выполняются как обычно только один раз без переименований файлов - checkouts теперь всегда будут в актуальном состоянии.

Для роутеров под большой нагрузкой предпочитаю все же использовать релиз с обновлениями безопасности. Стабильность в данном случае важнее, хотя и на Stable у многих крутятся серьёзные проекты. Тут вопрос идеологии и отношения..
На роутерах я использую следующий supfile

*default host=cvsup6.ua.freebsd.org

*default base=/var/db
*default prefix=/usr

*default release=cvs tag=RELENG_8_1
*default delete use-rel-suffix
*default compress

src-all
doc-all tag=.

Запуск csup проводится так (был указан в комментарии в supfile):

csup -L 2 /etc/supfile

Обновляем ядро.

Переходим в /usr/scr и начинаем процесс обновления.
Запаситесь терпением, так как это занимает 1-2 часа на P4

server# cd /usr/src/ 
server# rm -rf /usr/obj 
server# make -sj4 buildworld
Где j4 - компилировать в 4 потока. Рекомендуется для однопроцессорных машин, т.к. компиляция в большей степени требовательная к системе ввода-вывода, а не процессору. Для многопроцессорных это значение можно увиличить. s - уменьшает количество выводимой инфы на экран.

Для настройки системы можно использовать make.conf.
Пример смотрите здесь /usr/share/examples/etc/make.conf.

server# make -j4 buildkernel KERNCONF=MYKERNEL

Где MYKERNEL - ваше ядро. Без KERNCONF=MYKERNEL собирается с ядром GENERIC. В следующей строке поступаем соответственно.

server# make installkernel KERNCONF=MYKERNEL

Перезагрузимся

server# reboot
Перейдем в однопользовательский режим.
При загрузке жмем 4, либо из основного режима следующей командой.

server# shutdown now

Монтируем разделы файловой системы.

server# mount -u /  
#### Для UFS (стандартный вариант)
server# mount -a 
#### Для ZFS 
server# zfs mount -a 
server# mergemaster -p

Устанавливаем мир

server# cd /usr/src 
server# make installworld

Удаляем временные файлы

server# make delete-old

Сравниваем конфигурационные файлы

server# mergemaster

Несколько слов о работе этой утилиты.
Она сравнивает уже установленные файлы конфигурации с теми которые предлагаются новой версией FreeBSD. Если есть отличия, то на экране появляется сообщение об этом.
Первой строкой в нем идет имя файла, который не соответствует новым требованиям, а ниже сами отличия.
Знаком "-" помечаются строки, которые утилита собирается удалить,
а "+" - которые будут добавлены.
В конце предлагаются следующие варианты:
d - удалить предлагаемый вариант и оставить старый;
i - установить предлагаемый вариант, удалив старый;
m - сравнить построчно старый и предлагаемый вариант;
v - посмотреть отличия в файлах снова.

Чаще всего можно жать i, но иногда это может привести к замене ваших настроек на дефолтные.
Так что будте внимательны. Например, у меня установлен exim, а mergemaster предложил вернуть файл /etc/mail/mailer.conf в первоначальное состояние.
Это мне не нужно, поэтому выбираю m. Начинается построчное сравнение файлов.
Экран делится на две части, слева строки из старого файла, а справа из предлагаемого.
При нажатии на "Enter" выводятся возможные варианты последующих действий:
l - использовать вариант слевой стороны;
r - использовать вариант справой стороны; и т.д.
В моем случае, чтобы оставить старые настройки жмем "l".
После того как сравнение кончилось, предлагаются следующие варианты:
i - установить получившийся файл;
r - повторить сравнение снова;
v - просмотреть получивщийся файл.
Возможен также вариант, когда с новой версией системы появляются новые файлы, которых до этого не было.
В таком случае предлагается только 2 варианта:
d - удалить предлагаемый вариант и оставить старый;
i - установить предлагаемый вариант, удалив старый.
И в таком же духе сравниваются все файлы.
Перезагрузимся.

server# reboot 
server# cd /usr/src/ 
server# make delete-old-libs

Все. Проверяем.

server# uname -a

http://www.lissyara.su/articles/freebsd/tuning/make_buildworld/
http://www.lissyara.su/articles/freebsd/tuning/csup/
http://www.lissyara.su/articles/freebsd/tuning/make_kernel/
обновление системы из исходников

6 комментариев:

  1. Доброго дня.
    За статью огромный респкт и уважуха._)
    А вы не в курсе вот мне бы данную процедурку на фряхе
    7.3 сделать но блин)) боизно. Ядро GENERIC редактировал в свое время с опцией шифрования GEOM-ELI
    Вот и интересно после всех этих танцев не отвалиться у меня шифрование.

    ОтветитьУдалить
  2. С шифрованием не работал, нужды не было. По идее отвалиться ничего не должно. Но если там важные данные я б рекомендовал перестраховаться - заклонировать жесткий, либо как вариант проверить на другой машине, можно и виртуальной.

    ОтветитьУдалить
  3. ок. Попробую вариант с другой машиной. Предварительно идея такая. Сделать dupm поднять машину - развернуть на ней dump - пересобрать ядро и мир

    ОтветитьУдалить
  4. Если не сложно, напишите результат, самому интересно :)

    ОтветитьУдалить
  5. Alex,а не подскажете документацию нормальную по работе с GELI?

    ОтветитьУдалить
  6. шифрования GEOM-ELI - с ним проблем небыло при пересборке ядра и мира но это была лысая машина. минимум ПО. Как шлюз. А вот вариант сделать dump потом на другой тачке развернуть и юзать не прокатил (что и следовало ожидать))))) с учетом того что диске на машине где производился dump называются по другомму. Ну в связи с этим и пошла свястопляска по всей системе.
    Мне кажется если у вас 7.3 и много всякого дерьма)) стоит то лучше готовить отдельно тачку на 8.2

    ОтветитьУдалить