FreeBSDのベースパッケージを使ったアップグレード

投稿者: | 2021年5月28日

以下のような場合、FreeBSD をアップグレードすることは簡単ではないはずです。

  • Raspberry Pi のように freebsd-update でサポートされない Tier 2 プラットフォーム
  • なおかつ、リモート環境など、 OS がインストールされている micro SD カードなどを物理的に扱うことができない環境
  • buildworld しようにもメモリもディスクも容量が足りない環境

このような場合、最近では別環境でビルドしたベースパッケージを使ってアップグレードをするという方法があります。

前提

amd64, Raspberry Piの各モデル向けに各OSトレインのベースパッケージを作成する。

ビルドマシン

  • AMD64
  • 8vCPU
  • 8GB程度のメモリ
  • 200GB以上の高速なディスク
  • FreeBSD 12.2-RELEASE

所要時間の目安として、一つのOSトレイン一つのアーキテクチャ向けベースパッケージを作成すると当方の環境では30分弱程度かかりました。


ソースツリーのアップデート

/usr/local/bin/update-src.sh(subversion)

#!/bin/sh

if [ -x /usr/bin/svnlite ]; then
        SVN=svnlite
else
        SVN=svn
fi

#$SVN checkout https://svn.FreeBSD.org/base/releng/12.2 /usr/src-releng
#$SVN checkout https://svn.FreeBSD.org/base/stable/12 /usr/src-stable
#$SVN checkout https://svn.FreeBSD.org/base/head /usr/src-current
$SVN update /usr/src-releng
$SVN update /usr/src-stable
$SVN update /usr/src-current

/usr/local/bin/update-src.sh(git)

#!/bin/sh

#git clone -o upstream -b main https://git.freebsd.org/src.git
#git clone https://git.freebsd.org/src.git ssh://anongit@git.freebsd.org/src.git

#git clone https://git.freebsd.org/src.git /usr/src
#git clone -b releng/13.0 --depth 1 https://git.freebsd.org/src.git /usr/src-releng
#git clone -b stable/13 --depth 1 https://git.freebsd.org/src.git /usr/src-stable

cd /usr/src-stable
git config pull.ff only
git branch -v
git pull

cd /usr/src-releng
git config pull.ff only
git branch -v
git pull
cd /root

#git remote -v

アーキテクチャごとのビルド

/usr/local/bin/makeworld.sh

#!/bin/sh

if [ $# -lt 1 ]; then
        echo "$0 [current|stable|releng] [amd64|armv6|armv7|aarch64]"
        exit 255
fi

TRAIN="$1"
ARCH="amd64"

if [ $# -gt 1 ]; then
        ARCH="$2"
fi

MAKE="make -j 8"
WORLDLOG="buildworld-${ARCH}.log"
KERNELLOG="buildkernel-${ARCH}.log"
PACKAGESLOG="packages-${ARCH}.log"
MADEPACKAGES="packages"

case "${TRAIN}" in
"current"|"stable"|"releng")
        cd /usr/src-${TRAIN}
        case "${ARCH}" in
        "armv6"|"rpi")
                ${MAKE} buildworld      TARGET=arm TARGET_ARCH=armv6 UBLDR_LOADADDR=0x2000000 > ${WORLDLOG} 2>&1 && \
                ${MAKE} buildkernel     TARGET=arm TARGET_ARCH=armv6 KERNCONF=RPI-B > ${KERNELLOG} 2>&1 && \
                ${MAKE} ${MADEPACKAGES} TARGET=arm TARGET_ARCH=armv6 KERNCONF=RPI-B > ${PACKAGESLOG} 2>&1
                ;;
        "armv7"|"rpi2")
                if [ -f sys/arm/conf/RPI2 ]; then
                ${MAKE} buildworld      TARGET=arm TARGET_ARCH=armv7 UBLDR_LOADADDR=0x2000000 > ${WORLDLOG} 2>&1 && \
                ${MAKE} buildkernel     TARGET=arm TARGET_ARCH=armv7 KERNCONF=RPI2 > ${KERNELLOG} 2>&1 && \
                ${MAKE} ${MADEPACKAGES} TARGET=arm TARGET_ARCH=armv7 KERNCONF=RPI2 > ${PACKAGESLOG} 2>&1
                else
                ${MAKE} buildworld      TARGET=arm TARGET_ARCH=armv7 UBLDR_LOADADDR=0x2000000 > ${WORLDLOG} 2>&1 && \
                ${MAKE} buildkernel     TARGET=arm TARGET_ARCH=armv7 > ${KERNELLOG} 2>&1 && \
                ${MAKE} ${MADEPACKAGES} TARGET=arm TARGET_ARCH=armv7 > ${PACKAGESLOG} 2>&1
                fi
                ;;
        "aarch64"|"armv8"|"rpi3")
                ${MAKE} buildworld      TARGET=arm64 TARGET_ARCH=aarch64 > ${WORLDLOG} 2>&1 && \
                ${MAKE} buildkernel     TARGET=arm64 TARGET_ARCH=aarch64 > ${KERNELLOG} 2>&1 && \
                ${MAKE} ${MADEPACKAGES} TARGET=arm64 TARGET_ARCH=aarch64 > ${PACKAGESLOG} 2>&1
                ;;
        *)
                ${MAKE} buildworld      > ${WORLDLOG} 2>&1 && \
                ${MAKE} buildkernel     > ${KERNELLOG} 2>&1 && \
                ${MAKE} ${MADEPACKAGES} > ${PACKAGESLOG} 2>&1
                ;;
        esac
        ;;
*)
        ;;
esac

すべてのアーキテクチャのビルド

/usr/local/bin/makeworld-all.sh

#!/bin/sh

ARCHITECTURE="amd64 armv6 armv7 aarch64"
RELS="releng stable current"

for rel in ${RELS}
do
        chflags -R noschg /usr/obj/usr/src-$rel
        rm -rf /usr/obj/usr/src-$rel
        for arch in ${ARCHITECTURE}
        do
                /usr/local/bin/makeworld.sh $rel $arch
        done
done

アップグレード

ローカルアップグレード設定

/usr/local/etc/pkg/repos/FreeBSD-base.conf

FreeBSD-base: {
        file: "/usr/obj/usr/src-stable/repo/${ABI}/latest",
        mirror_type: "none",
        enabled: yes
}

リモートアップグレード設定

ビルドしたベースパッケージを HTTP サーバーでアクセスできるようにしておき、そのパッケージサーバーからパッケージを取得します。

/usr/local/etc/apache24/Includes/freebsd-base.conf

Alias /repo "/usr/obj/usr/src-stable/repo"
<Directory "/usr/obj/usr/src-stable/repo">
        Options Indexes FollowSymLinks
        AllowOverride None
        Require local
        Require ip 192.168.0.0/16
</Directory>

/usr/local/etc/pkg/repos/FreeBSD-base.conf

FreeBSD-base: {
        url: "http://pkg.example.com/repo/${ABI}/latest",
        enabled: yes
}

ベースパッケージの初期化

rsync -av /etc/ /etc.old/
pkg update -r FreeBSD-base
pkg install -y -g 'FreeBSD-*'
rm -rf /etc
rsync -av /etc.old/ /etc/

アップグレード

マイナーアップグレードの実行

既存パッケージのアップグレードと、追加パッケージのインストールを行います。

mergemaster -p
pkg update -r FreeBSD-base
pkg upgrade -y -r FreeBSD-base
pkg install -y -r FreeBSD-base -g 'FreeBSD-*'
reboot
mergemaster

メジャーアップグレードの実行

FreeBSD 11 から 12 のようにメジャーバージョンをアップグレードするときは明示的に ABI を指定します。また、不要になった古いパッケージを削除します。

mergemaster -p
rsync -av /etc/ /etc.old/
env ABI=FreeBSD:12:amd64 pkg upgrade -y -r FreeBSD-base
env ABI=FreeBSD:12:amd64 pkg install -y -r FreeBSD-base -g 'FreeBSD-*'
pkg remove -y 'FreeBSD-*-11*'
rm -rf /etc
mv /etc.old /etc
reboot
mergemaster
pkg-static upgrade -y -r FreeBSD pkg
pkg update -r FreeBSD
pkg upgrade -y -r FreeBSD

保存されたファイルを削除します。

find / -name "*.pkgsave" -print | xargs rm -f
find / -name "*.pkgnew" -print | xargs rm -f

CURRENTのアップグレード

CURRENTからCURRENTへアップグレードするときはライブラリ関係の問題を避けるためにpkg-staticを使います。また、不要になった古いパッケージを削除します。
また、open-vm-toolsを動かしている場合は、カーネルモジュールが動作しなくなる可能性があるので一時的に削除して、アップグレードが終わったら再度インストールするようにします。

mergemaster -p
rsync -av /etc/ /etc.old/
pkg-static install -y -r FreeBSD-base -g 'FreeBSD-*'
pkg-static remove -y 'FreeBSD-*-14.snap2021*'
pkg remove -y open-vm-tools
rm -rf /etc
mv /etc.old /etc
reboot
mergemaster
pkg update -r FreeBSD
pkg upgrade -y -r FreeBSD
pkg install -y -r FreeBSD open-vm-tools

パッケージ構築の自動化

/usr/local/bin/build-updated-src.sh

#!/bin/sh

CURRENT=`uname -r`
SRC="/usr/src/sys/conf/newvers.sh"

/usr/local/bin/update-src.sh
/usr/local/bin/update-ports.sh

REVISION=`grep REVISION ${SRC} | grep -v ^# | head -1 | awk -F'"' '{ printf("%s", $2); }'`
BRANCH=`grep BRANCH ${SRC} | grep -v ^# | head -1 | awk -F'"' '{ printf("%s", $2); }'`
RELEASE="${REVISION}-${BRANCH}"

if [ "${CURRENT}" = "${RELEASE}" ]; then
        exit
fi

echo "Build Base Package"
/usr/local/bin/makeworld-all.sh

付録

installworldによるローカルアップグレード

installworld.sh

#!/bin/sh
set -x
if [ $# -lt 1 ]; then
        echo "$0 [current|stable|releng] [amd64|armv6|armv7|aarch64]"
        exit 255
fi

DEST="/dest"
TRAIN="$1"
ARCH="amd64"

if [ $# -gt 1 ]; then
        ARCH="$2"
fi

MAKE="make"

case "${TRAIN}" in
"current"|"stable"|"releng")
        cd /usr/src-${TRAIN}
        case "${ARCH}" in
        "armv6"|"rpi")
                ${MAKE} installkernel   TARGET=arm TARGET_ARCH=armv6 KERNCONF=RPI-B DESTDIR=${DEST} && \
                ${MAKE} installworld    TARGET=arm TARGET_ARCH=armv6 DESTDIR=${DEST} && \
                ${MAKE} delete-old      TARGET=arm TARGET_ARCH=armv6 DESTDIR=${DEST} && \
                ${MAKE} delete-old-libs TARGET=arm TARGET_ARCH=armv6 DESTDIR=${DEST}
                ;;
        "armv7"|"rpi2")
                ${MAKE} installkernel   TARGET=arm TARGET_ARCH=armv7 KERNCONF=RPI2 DESTDIR=${DEST} && \
                ${MAKE} installworld    TARGET=arm TARGET_ARCH=armv7 DESTDIR=${DEST} && \
                ${MAKE} delete-old      TARGET=arm TARGET_ARCH=armv7 DESTDIR=${DEST} && \
                ${MAKE} delete-old-libs TARGET=arm TARGET_ARCH=armv7 DESTDIR=${DEST}
                ;;
        "aarch64"|"armv8"|"rpi3")
                ${MAKE} installkernel   TARGET=arm64 TARGET_ARCH=aarch64 DESTDIR=${DEST} && \
                ${MAKE} installworld    TARGET=arm64 TARGET_ARCH=aarch64 DESTDIR=${DEST} && \
                ${MAKE} delete-old      TARGET=arm64 TARGET_ARCH=aarch64 DESTDIR=${DEST} && \
                ${MAKE} delete-old-libs TARGET=arm64 TARGET_ARCH=aarch64 DESTDIR=${DEST}
                ;;
        *)
                ${MAKE} installworld && \
                ${MAKE} installkernel && \
                ${MAKE} delete-old && \
                ${MAKE} delete-old-libs
                ;;
        esac
        ;;
*)
        ;;
esac

参考

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です