Home

Обновляем FreeBSD удалённо

Преамбула.

В хэндбуке FreeBSD написано, что нужно делать перезагрузку в single mode в процессе обновления системы. На рабочих серверах это архисложно, особенно если их десятки и через них гоняется трафик сотнями мегабит в секунду.

Поэтому я уже много лет обновляю FreeBSD удалённо через SSH пока без каких-либо проблем. Кроме единственного случая в стародавние времена на ветке 7.X, но я чего-то там походу напортачил в процессе, поэтому пришлось ехать к машине и пользоваться директорией /rescue при этом вкуривая интернет с соседней машины. Была весёлая ночь.

До пересборки системы FreeBSD я обновил её исходники через SVN репозиторий (subversion). Читай мой предыдущий пост. Теперь могу приступить к пересборке текущей STABLE версии из исходников. Бинарные обновления не делаю, потому что они создаются (насколько я знаю) без оптимизации под архитектуру. У меня это athlon64.

Обновлять FreeBSD будем из исходников, поэтому как минимум нужно обновить исходники FreeBSD.

Обновляем FreeBSD удалённо.

# cd /usr/src/

# mergemaster -p

В хэндбуке написано, что это надо делать где-то в середине процесса, да ещё и в single mode. Я делаю это в самом начале и позже ты поймёшь почему.

Обновляем файлы с крайней осторожностью! Обычно оно обновляет два файла - список юзеров (/etc/passwd) и список групп (/etc/group). Если обновишь так, что удалится твой юзер, то на машину после ребута ты уже не попадёшь. Нужно будет ехать к ней и менять пароли через single mode.

# make -j8 buildworld

-j4 я делаю на 4х процессорной машине, на 8ми процессорной делаю -j8. Хотя говорят можно делать и по 4 процесса на ядро. На какой-то мощной машине я делал -j16 - мир пересобирался минут за 20. Но мне спешить некуда, поэтому обычно я делаю -j8.

# make -j8 buildkernel

так собрал ядро. Искал тут инфу как можно обновить FreeBSD 7.X до 9.X - вместо этого наткнулся на статью на хабре, где сначала собирают ядро (buildkernel), а потом world (buildworld). Не знаю, мир перевернулся что ли?! В русской версии хэндбука по-прежнему написано, что сначала buildworld, потом buildkernel - не вижу причин противоречить handbook'у в данном случае.

Устанавливаем ядро.

# make installkernel

Где-то теперь по FreeBSD handbook полагается shutdown now и так далее. Но на удалённой машине этого не сделаешь, поэтому дальше устанавливаем мир.

# make installworld

теперь нужно запустить mergemaster для обновления разных скриптов и конфигов. Нажимать y на необновлённых файлах меня не радует, поэтому запускаем с параметром -iU.

# mergemaster -iU

Возможно будет спрашивать про обновление разных файлов. Обновляем с осторожностью - система-то удалённая, а ехать к ней не хочется. При обновлении первой строки с номером версии файла выбирай правый вариант, то есть обновлённый. А дальше выбирай левый вариант, если тебе нужно сохранить твои изменения. Точно также надо было действовать в начале при выполнении команды mergemaster -p. Если в начале ты не обновил верхнюю строку, то ты ещё можешь это сделать, чтобы при следующем обновлении системы оно не задавало вопросы про эти файла, если там не появлялось никаких изменений.

В конце оно будет спрашивать запустить ли rebuild разных файлов типа newaliases - я отвечаю y - по умолчанию там выбрано n.

Ну и теперь перезагружаем систему.

# reboot

Через минуту-две машина возвращается онлайн и мы продолжаем с ней работать, если нужно или же у неё поднимаются все сервисы и она продолжает работать в штатном режиме.

 

Всё тоже самое можно делать в три строки. И это очень удобно, потому что запустил процесс и забыл про сервер на пару часов, а не сидишь и мониторишь его, когда он там пришёл к следующему шагу. И это как раз та причина, почему я mergemaster -p делаю в самом начале.

# mergemaster -p
# make -j8 buildworld && make -j8 buildkernel && make installkernel && make installworld && mergemaster -iU
# reboot

Обращаю внимание, что нужно пользовать именно два амперсанда - && - если в каком-то шаге произойдёт ошибка, то следующая команда выполняться не будет. И тогда уже будешь делать всё пошагово и смотреть в чём проблема.

 

PS

Вот и мои два FreeBSD сервера поднялись и при логине на них они теперь указывают, по всей видимости, версию SVN-исходников, на основании которых собрана FreeBSD. Выглядит это так:

FreeBSD 9.1-PRERELEASE (KMD) #0 r243371M: Wed Nov 21 18:15:48 MSK 2012

У тебя скорее всего вместо KMD будет написано GENERIC. То есть ядро по умолчанию. Я собираю обычно кастомное ядро, даже если в нём нет никаких изменений. Просто мне так удобнее понимать, что система пересобрана с моими настройками, например, с оптимизацией под процессор athlon64. При этом у меня:

В /etc/make.conf добавлены строки:

CPUTYPE?=athlon64
KERNCONF=KMD

?= означает, что нужно собирать систему без жёсткой привязки к архитектуре, насколько я понимаю, то есть собранная так система запускалась у меня как-то на athlon-xp без особых проблем.

Файл KMD выглядит так:

include         GENERIC
ident           KMD

А в директории
/usr/src/sys/amd64/conf
у меня сделан symlink на файл KMD (не забудь находиться в указанной выше директории), который лежит в моей домашней директории.
ln -s /usr/home/<user>/KMD

 

PS2

Иногда для чистоты сборки системы, особенно при апгрейде с одной версии на другую нужно зачищать директорию /usr/obj/

# rm -r /usr/obj/

Если оно на что-то ругнулось и/или директория не удалилась, то выполняем следующую команду, а потом повторяем предыдущую.

# chflags -R noschg /usr/obj/

 

PS3

Для чистоты обновления системы залез в английский FreeBSD handbook выяснить относительно текущего состояния make delete-olds.

Делаем:

# cd /usr/src
# make check-old

Если выдаёт что-то отличное от:

root@www9:/usr/src # make check-old
>>> Checking for old files
>>> Checking for old libraries
>>> Checking for old directories
To remove old files and directories run 'make delete-old'.
To remove old libraries run 'make delete-old-libs'.

Например, у меня выдало:

root@www9:/usr/src # make check-old
>>> Checking for old files
/usr/include/clang/3.1/unwind.h
/etc/auth.conf
/usr/share/examples/etc/auth.conf
/usr/share/man/man3/auth.3.gz
/usr/share/man/man5/auth.conf.5.gz
/usr/include/clang/3.0/altivec.h
/usr/include/clang/3.0/avxintrin.h
/usr/include/clang/3.0/emmintrin.h
/usr/include/clang/3.0/immintrin.h
/usr/include/clang/3.0/mm3dnow.h
/usr/include/clang/3.0/mm_malloc.h
/usr/include/clang/3.0/mmintrin.h
/usr/include/clang/3.0/nmmintrin.h
/usr/include/clang/3.0/pmmintrin.h
/usr/include/clang/3.0/smmintrin.h
/usr/include/clang/3.0/tmmintrin.h
/usr/include/clang/3.0/wmmintrin.h
/usr/include/clang/3.0/x86intrin.h
/usr/include/clang/3.0/xmmintrin.h
/usr/share/man/man9/net_add_domain.9.gz
>>> Checking for old libraries
>>> Checking for old directories
/usr/include/clang/3.0
/usr/include/c++/v1/ext
/usr/include/c++/v1
To remove old files and directories run 'make delete-old'.
To remove old libraries run 'make delete-old-libs'.

Поэтому я выполнил:

# make delete-old

Однако, чтобы не подтверждать удаление каждого файла вручную, делаем так:

# yes|make delete-old

На выходе будет что-то типа этого:

root@www9:/usr/src # yes | make delete-old
>>> Removing old files (only deletes safe to delete libs)
remove /usr/include/clang/3.1/unwind.h? remove /etc/auth.conf? remove /usr/share/examples/etc/auth.conf? remove /usr/share/man/man3/auth.3.gz? remove /usr/share/man/man5/auth.conf.5.gz? remove /usr/include/clang/3.0/altivec.h? remove /usr/include/clang/3.0/avxintrin.h? remove /usr/include/clang/3.0/emmintrin.h? remove /usr/include/clang/3.0/immintrin.h? remove /usr/include/clang/3.0/mm3dnow.h? remove /usr/include/clang/3.0/mm_malloc.h? remove /usr/include/clang/3.0/mmintrin.h? remove /usr/include/clang/3.0/nmmintrin.h? remove /usr/include/clang/3.0/pmmintrin.h? remove /usr/include/clang/3.0/smmintrin.h? remove /usr/include/clang/3.0/tmmintrin.h? remove /usr/include/clang/3.0/wmmintrin.h? remove /usr/include/clang/3.0/x86intrin.h? remove /usr/include/clang/3.0/xmmintrin.h? remove /usr/share/man/man9/net_add_domain.9.gz?
>>> Old files removed
>>> Removing old directories
/usr/include/clang/3.0
/usr/include/c++/v1/ext
/usr/include/c++/v1
>>> Old directories removed
To remove old libraries run 'make delete-old-libs'.

 

Так как old libraries не были замечены, то их удалять и не стал, ибо нечего.