dadv: (chuck)
[personal profile] dadv

Удаленная бинарная миграция FreeBSD с 8.2-RELEASE/i386 на 8.2-RELEASE/amd64 без доступа к консоли с двумя перезагрузками и минимальным downtime, безопасная настолько, насколько это возможно при обновлении "по месту". С некоторыми оговорками работает и для миграции c 8.2-STABLE.

Требуется доступность FreeBSD-8.2-RELEASE-amd64-livefs.iso (333MB). Быстрый и простой способ требует, чтобы на корневом разделе было свободно 64MB и дополнительно 401MB на разделе /var. Все команды выполняем от рута, используя шелл семейства sh/zsh/bash или подобный (на csh/tcsh не рассчитаны). В системе нужен пользователь (не root) группы wheel, шелл которого лежит в корневой файловой системе или в /usr.

  1. Скачать образ FreeBSD-8.2-RELEASE-amd64-livefs.iso.

  2. Установить xorriso из портов или пакетов для корректного раскрытия образа (штатные mdconfig и bsdtar не годятся: при раскрытии iso через mdconfig ломаются хардлинки, а bsdtar теряет атрибуты файлов).

  3. TMPDIR устанавливаем в какой-нибудь каталог раздела /var.
    Разворачиваем образ, игнорируя ошибки касательно boot.catalog:

    TMPDIR=/var/tmp/work
    mkdir -p $TMPDIR
    cd $TMPDIR
    rm -rf livefs
    xorriso -for_backup -load volid \* -indev /path/to/FreeBSD-8.2-RELEASE-amd64-livefs.iso -osirrox on -- -extract / livefs -rollback_end


  4. Занимаем 49MB в /boot:

    cp -rp livefs/boot/kernel /boot/kernel.GENERIC64

  5. Подготовка mfsroot.

    Копируем минимально необходимый набор файлов для успешного удаленного входа:

    cd /etc
    cp -rp fstab hostid host.conf nsswitch.conf rc.conf ssh resolv.conf passwd group master.passwd pwd.db spwd.db $TMPDIR/livefs/etc


    Стоит убедиться, что в $TMPDIR/livefs/etc/resolv.conf указан обслуживающий нас DNS-сервер, а не 127.0.0.1 лишь только и при необходимости отредактировать этот файл.

    Теперь нужно привести $TMPDIR/livefs/etc/fstab к примерно следующему виду:
    # Device                Mountpoint      FStype  Options         Dump    Pass#
    /dev/md0.uzip           /               ufs     ro              0       0
    /dev/md1.uzip           /usr            ufs     ro              0       0
    /dev/ad0s1b             none            swap    sw              0       0
    /dev/ad0s1a             /mnt            ufs     rw              2       0
    /dev/ad0s1e             /mnt/var        ufs     rw              2       0
    /dev/ad0s1d             /mnt/usr        ufs     rw              2       2

    Первые две строки обязательно такие, остальные - из оригинального fstab, точку монтирования для рута заменяем на /mnt, /usr и /var тоже смещаем внутрь /mnt, остальные файловые системы (если есть) намеренно не упоминаем. Колонки Dump и Pass заполняем указанными значениями.

    Создаём файл rc.initdiskless:

    cd $TMPDIR/livefs/etc
    touch diskless
    cat > rc.initdiskless <<EOF
    #!/bin/sh
    cd /
    
    for fs in /mnt /mnt/var
    do
      if fsck -p \$fs || fsck -y \$fs; then
        mount \$fs
      else
        exit 1
      fi
    done
    
    mdconfig -af $TMPDIR/usr.uzip -u1
    mount /usr
    
    mdconfig -at malloc -s 5M -u2
    newfs /dev/md2
    mount -o async /dev/md2 /etc
    tar -xpzf $TMPDIR/etc.tgz
    EOF

    В $TMPDIR/livefs/etc/rc.conf желательно отключить все сервисы, кроме
    sshd и каналообразующих (учитывать, что грузиться будет GENERIC), что-то типа этого:

    root_rw_mount="NO"              # эта строка обязательна
    hostname="host.domain.ru"
    defaultrouter="x.x.x.x"
    ifconfig_em0="inet x.x.x.y/24"
    sendmail_enable="NONE"
    firewall_enable="NO"
    inetd_enable="NO"
    sshd_enable="YES"
    fsck_y_enable="YES"
    background_fsck="NO"

  6. Создаём свои образы, уменьшая размер:
    alias mkfs='makefs -t ffs -o bsize=4096 -o fsize=512 -o minfree=3 -o optimization=space'
    cd $TMPDIR/livefs
    rm -rf boot tmp var usr/games usr/include usr/share
    ln -s /mnt/var .
    ln -s /mnt/tmp .
    ln -s /mnt/boot .
    ln -s /mnt/home .
    (
      cd usr; ln -s /mnt/usr/include .; ln -s /mnt/usr/share .
      chmod u+s bin/su
      mkfs $TMPDIR/usr .
    )
    rm -r usr; mkdir usr
    mkuzip ../usr; rm ../usr
    
    tar czf ../etc.tgz etc
    find -d etc \! -name etc -a \! -name rc -a \! -name fstab -a \! -name diskless\
     -a \! -name rc.initdiskless -a \! -name login.conf.db -a \! -name group -delete
    mkfs ../mfsroot .
    cd ..
    rm -r livefs
    mkuzip mfsroot; rm mfsroot
    
    cp -rp /etc .
    echo 'ldconfig32_paths="$ldconfig32_paths /lib /usr/lib /usr/local/lib /usr/local/lib/compat/pkg"' >> etc/rc.conf

  7. Подгрузка полученного mfsroot, занимаем ещё 8.2MB в /boot:

    cd /boot
    mv $TMPDIR/mfsroot.uzip .
    cat <<EOF > nextboot.conf
    nextboot_enable="YES"
    kernel="kernel.GENERIC64"
    geom_uzip_load="YES"
    mfsroot_load="YES"
    mfsroot_type="mfs_root"
    mfsroot_name="/boot/mfsroot.uzip"
    vfs.root.mountfrom="ufs:/dev/md0.uzip"
    vfs.root.mountfrom.options="ro"
    EOF

  8. Перезагружаем систему, она загружается с /boot/kernel/kernel.GENERIC64 и монтирует в качестве корня изготовленный mfsroot.uzip с бинарниками архитектуры amd64, запускает sshd. Входим нашим пользователем (см. выше), при помощи su поднимаем привилегии. Теперь можно обновиться (файловые системы смонтированы в /mnt) любым удобным способом. Это - точка невозврата, сейчас ещё можно перезагрузить систему и она вернется в исходное состояние. Дальше уже нет, возврат только через восстановление из бекапов с консоли.

    Я обновлял через sysinstall по сети:

    find /mnt -maxdepth 3 -flags +schg -exec chflags noschg {} +
    sysinstall


    В меню Options сменить Install Root на /mnt.
    Выбрать режим Upgrade, в меню Choose Distributions выбрать Custom и там пометить только base и lib32 (ядро уже установлено). Установка с FTP проходит совершенно гладко. После окончания установки выходим из sysinstall. Далее:

    echo 'kernel="kernel.GENERIC64"' >> /mnt/boot/loader.conf
    mv /mnt/etc /mnt/etc.0
    cp -rp /mnt/var/tmp/work/etc /mnt # тут используем путь вида /mnt/$TMPDIR/etc.

    Снова перезагружаемся, теперь система грузится уже не с образа mfsroot, а штатно.

После перезагрузки можно удалить /boot/mfsroot.uzip и $TMPDIR. Базовая система обновлена и должна работать штатно. Если производилась миграция со STABLE, самое время выполнить стандартный source upgrade.

Что касается установленного стороннего софта, тут возможны варианты:

  • Не будут работать сторонние модули ядра до их обновления на версии amd64. Для модулей ядра важно, чтобы в /usr/src/sys на момент сборки лежали в точности те же исходники, из которых собрано ядро, с которым будет запускаться модуль. Например, если в /usr/src/sys лежат исходники от 8.2-STABLE, то собранный с ними сторонний ядерный модуль может не заработать с ядром от 8.2-RELEASE.
  • Подавляющее большинство прикладного софта будет работать как ни в чём не бывало при условии прописывания в /etc/rc.conf строки ldconfig32_paths (см. выше) со всеми путями, где лежат нужные программам разделяемые библиотеки.

Например, после выполнения этой миграции для моего десктопа и подмены nvidia.ko на версию amd64 (не переустановки драйвера из портов целиком!) у меня заработали установленные ранее xorg-7.4_2, xfce4, OpenOffice, игры с использованием 3D-ускорения NeverBall и Quake3 OpenArena после приведения ldconfig32_paths к такому виду:

ldconfig32_paths="$ldconfig32_paths /lib /usr/lib /usr/local/lib /usr/local/lib/compat/pkg /usr/local/lib/event2 /usr/local/lib/gcc44 /usr/local/lib/xorg/modules/extensions /usr/local/lib/gegl-0.1 /usr/local/lib/graphviz /usr/local/lib/libxul /usr/local/lib/nss /usr/local/lib/qt4 /usr/local/lib/virtualbox /usr/local/lib/zsh /usr/local/lib/firefox /usr/local/openoffice.org-OOO310_m18/openoffice.org/ure/lib /usr/local/openoffice.org-OOO310_m18/openoffice.org/basis3.1/program"

Команда ldconfig -32 -m dir позволяет добавлять новые каталоги без перезагрузки.

Не заработал firefox4: до убирания ~/.mozilla при старте FF сразу делал exit(1), а после убирания стал сразу падать с SIGSEGV.

Поэтому, следующим шагом может быть удаление всех пакетов и переустановка их версий для amd64 - пакетами или просто пересборкой из портов.

N.B.: автор не несет ответственности за выполнение указанной процедуры без полных и протестированных бекапов и без тренировки в лабораторных условиях. Неаккуратное выполнение команд из последнего пункта ПРИВЕДЕТ вашу систему в состояние, когда для её загрузки требуется восстановление с консоли.

Date: 2011-06-22 12:01 (UTC)
From: [identity profile] dmarck.livejournal.com
Я всю жизнь для подобного пользовался установкой (и последующей однократной загрузкой) в своп ;-P

Date: 2011-06-22 12:44 (UTC)
From: [identity profile] dadv.livejournal.com
Ну, а можно и так, без установки в своп. Свопа, кстати, может и не быть ;-) А ещё, помнится, была такая штука как своп через NFS :-)

Profile

dadv: (Default)
Choose your future

July 2024

M T W T F S S
12 34567
891011121314
15161718192021
22232425262728
293031    

Tags

Style Credit

Powered by Dreamwidth Studios