11.2 Rocky Linux 兼容层
FreeBSD 通过 emulators/linux-rl9 Port(内置 linux_base-rl9)提供 Rocky Linux 9.7 兼容层。本节介绍安装步骤、版本验证及基础配置。
11.2.1 通过 FreeBSD Ports 安装 Rocky Linux 兼容层
11.2.1.1 Rocky Linux 版本号概述
截至 2026 年 2 月 16 日,FreeBSD Ports 的 emulators/linux-rl9(其实际对应的基础包为 emulators/linux_base-rl9)基于 Rocky Linux 9.7 发行版构建。
在 Rocky Linux 兼容层环境中查看当前 Linux 发行版的版本信息:
sh
bash-5.1$ cat /etc/redhat-release # Rocky Linux 兼容层内
Rocky Linux release 9.7 (Blue Onyx)该版本号仅具有参考意义,并非绝对标识。/etc/redhat-release 文件由 Rocky Linux 的 rocky-release 软件包提供,内容为静态文本。Linux 发行版本质上是多个独立软件包的集合。单一软件包的版本信息无法断定发行版中所有软件包均属于同一版本,因此 Linux 发行版的版本号是一个相对概念。
进一步,观察提交 emulators/linux_base-rl9: update to Rocky Linux 9.7 (+),真正决定版本号的是 Ports 框架中的 Mk/Uses/linux.mk 文件中的 LINUX_DIST_VER 变量的值:
make
. if empty(linux_ARGS)
. if exists(${LINUXBASE}/etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7) # 检查兼容层内是否存在文件 RPM-GPG-KEY-CentOS-7,如果有则为 CentOS 7 兼容层
linux_ARGS= c7
. elif exists(${LINUXBASE}/etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9) # 检查兼容层内是否存在文件 RPM-GPG-KEY-Rocky-9,如果有则为 Rocky Linux 9 兼容层
linux_ARGS= rl9
. else
linux_ARGS= ${LINUX_DEFAULT}
. endif
. endif
. if ${linux_ARGS} == c7 # 检查是不是 CentOS 7 兼容层
LINUX_DIST_VER?= 7.9.2009 # 当前引入的是 CentOS 7.9.2009
. elif ${linux_ARGS} == rl9 # 检查是否为 Rocky Linux 9 兼容层
LINUX_DIST_VER?= 9.7 # 当前引入的是 Rocky Linux 9.7
. else
ERROR+= "Invalid Linux distribution: ${linux_ARGS}" # 如果都不是则直接打印报错信息
. endif11.2.1.2 启用 Linux 兼容层服务
安装 Rocky Linux 兼容层前,需先启用 Linux 兼容层服务。
启用 Linux 兼容层服务,并设置为开机自启:
sh
# service linux enable立即启动 Linux 兼容层服务:
sh
# service linux start11.2.1.3 安装基本系统
- 使用 pkg 安装:
sh
# pkg install linux-rl9- 也可使用 Ports 安装:
sh
# cd /usr/ports/emulators/linux-rl9/
# make install clean11.2.1.4 配置相关服务
安装完成后,还需配置相关服务。
sh
# service dbus enable # 通常桌面环境已经配置
# service dbus start # 通常桌面环境已经配置无需配置 /etc/fstab 文件,通过自动运行的 linux_mounts_enable 服务将挂载所需文件系统条目。
重启系统后生效。
11.2.2 通过 Shell 脚本安装 Rocky Linux 兼容层
sh
#!/bin/sh
ROOT_DIR=/compat
DIST=rocky
DIST_FULLNAME="Rocky Linux"
VER=9
SUB_VER=7
TIME_VER="latest"
SORT=Base
FILE=Rocky-${VER}-Container-${SORT}.${TIME_VER}.x86_64.tar.xz
SUBDIR=""
URL=https://mirrors.ustc.edu.cn/${DIST}/${VER}.${SUB_VER}/images/x86_64
UPDATE_CMD="dnf makecache"
UPGRADE_CMD="dnf upgrade -y"
INSTALL_CMD="dnf install -y"
UPDATE=1
UPGRADE=1
INSTALL=1
echo "Starting ${DIST_FULLNAME} installation"
sleep 0.5
# 检查 Linux 模块
echo "Checking required modules"
if [ "$(sysrc -n linux_enable)" != "YES" ]; then
echo "linux service is not enabled. Enable it now? (Y|n)"
read ANSWER
case $ANSWER in
[Nn][Oo]|[Nn])
echo "Warning: You MUST start linux service with \"service linux start\" EACH TIME FreeBSD IS REBOOTED."
echo "Sure to continue without enabling linux service? (y|N)"
read ANSWER
case $ANSWER in
[Yy][Ee][Ss]|[Yy])
echo "WARNING: linux module not enabled"
;;
[Nn][Oo]|[Nn]|"")
echo "Enabling linux module"
sysrc linux_enable=YES
;;
*)
echo "Aborting."
exit 4
;;
esac
;;
[Yy][Ee][Ss]|[Yy]|"")
echo "Enabling linux module"
sysrc linux_enable=YES
;;
*)
echo "Aborting."
exit 4
;;
esac
fi
echo "Starting linux service"
service linux start
# 检查 dbus
if ! which -s dbus-daemon; then
echo "dbus-daemon not found. Install dbus now? (Y|n)"
read ANSWER
case $ANSWER in
[Nn][Oo]|[Nn])
echo "Aborting. dbus not installed"
exit 2
;;
[Yy][Ee][Ss]|[Yy]|"")
echo "Installing dbus"
pkg install -y dbus
;;
*)
echo "Aborting."
exit 4
;;
esac
fi
if [ "$(sysrc -n dbus_enable)" != "YES" ]; then
echo "dbus is not enabled. Enable it now? (Y|n)"
read ANSWER
case $ANSWER in
[Nn][Oo]|[Nn])
echo "WARNING: You MUST start dbus with \"service dbus start\" EACH TIME FreeBSD IS REBOOTED."
echo "Sure to continue without enabling dbus? (y|N)"
read ANSWER
case $ANSWER in
[Yy][Ee][Ss]|[Yy])
echo "Warning: dbus service not enabled"
;;
[Nn][Oo]|[Nn]|"")
echo "Enabling dbus service"
service dbus enable
;;
*)
echo "Aborting."
exit 4
;;
esac
;;
[Yy][Ee][Ss]|[Yy]|"")
echo "Enabling dbus service"
service dbus enable
;;
*)
echo "Aborting."
exit 4
;;
esac
fi
if [ -z "$(ps aux | grep dbus | grep -v grep)" ]; then
echo "Starting dbus service"
service dbus start
fi
# 检查 nullfs
if [ "$(sysrc -f /boot/loader.conf -qn nullfs_load)" != "YES" ]; then
echo "nullfs should be loaded on boot. Set nullfs_load to YES? (Y|n)"
read ANSWER
case $ANSWER in
[Nn][Oo]|[Nn])
echo "Warning: You MUST load nullfs with \"kldload -v nullfs\" EACH TIME FreeBSD IS REBOOTED."
echo "Sure to continue without setting nullfs_load to YES? (y|N)"
read ANSWER
case $ANSWER in
[Yy][Ee][Ss]|[Yy])
echo "Warning: nullfs_load not set"
;;
[Nn][Oo]|[Nn]|"")
echo "Setting nullfs_load to YES"
sysrc -f /boot/loader.conf nullfs_load="YES"
;;
*)
echo "Aborting."
exit 4
;;
esac
;;
[Yy][Ee][Ss]|[Yy]|"")
echo "Setting nullfs_load to YES"
sysrc -f /boot/loader.conf nullfs_load="YES"
;;
*)
echo "Aborting."
exit 4
;;
esac
fi
if ! kldstat -n nullfs >/dev/null 2>&1; then
echo "Loading nullfs module"
kldload -v nullfs
fi
# 下载和解压基本系统
echo "${DIST_FULLNAME} will be installed in ${ROOT_DIR}/${DIST}"
echo "Downloading basic system"
fetch ${URL}/${FILE}
echo "Extracting basic system"
sleep 0.5
mkdir -p ${ROOT_DIR}/${DIST}
tar xvpf ${FILE} ${SUBDIR:-} -C ${ROOT_DIR}/${DIST} --numeric-owner
# 挂载必要文件系统
echo "Mounting required file system"
sleep 0.5
echo "devfs ${ROOT_DIR}/${DIST}/dev devfs rw,late 0 0" >> /etc/fstab
echo "tmpfs ${ROOT_DIR}/${DIST}/dev/shm tmpfs rw,late,size=1g,mode=1777 0 0" >> /etc/fstab
echo "fdescfs ${ROOT_DIR}/${DIST}/dev/fd fdescfs rw,late,linrdlnk 0 0" >> /etc/fstab
echo "linprocfs ${ROOT_DIR}/${DIST}/proc linprocfs rw,late 0 0" >> /etc/fstab
echo "linsysfs ${ROOT_DIR}/${DIST}/sys linsysfs rw,late 0 0" >> /etc/fstab
echo "/tmp ${ROOT_DIR}/${DIST}/tmp nullfs rw,late 0 0" >> /etc/fstab
mount -al
# 配置 DNS
echo "Should ${DIST_FULLNAME} use Alibaba DNS or local resolv.conf? ((A)li | (L)ocal | (C)ancel)"
read ANSWER
case $ANSWER in
[Aa][Ll][Ii]|[Aa]|"")
echo "Setting Alibaba DNS"
echo "nameserver 223.5.5.5" >> ${ROOT_DIR}/${DIST}/etc/resolv.conf
DNS_CONFIGURED=1
;;
[Ll][Oo][Cc][Aa][Ll]|[Ll])
echo "Using local resolv.conf"
cp /etc/resolv.conf ${ROOT_DIR}/${DIST}/etc/resolv.conf
DNS_CONFIGURED=1
;;
*)
echo "Canceled."
echo "You have to edit ${ROOT_DIR}/${DIST}/etc/resolv.conf by yourself!"
DNS_CONFIGURED=0
;;
esac
# 设置 USTC 镜像源
echo "Do you want to use USTC source for ${DIST_FULLNAME}? (Y|n)"
read ANSWER
case $ANSWER in
[Yy][Ee][Ss]|[Yy]|"")
echo "Setting USTC source"
chroot ${ROOT_DIR}/${DIST} /bin/bash -c "sed \
-e 's|^mirrorlist=|#mirrorlist=|g' \
-e 's|^#baseurl=http://dl.rockylinux.org/\$contentdir|baseurl=https://mirrors.ustc.edu.cn/rocky|g' \
-i.bak \
/etc/yum.repos.d/rocky-extras.repo \
/etc/yum.repos.d/rocky.repo"
;;
[Nn][Oo]|[Nn])
echo "Will not set USTC source. Skipping update, upgrade and installation."
UPDATE=0
UPGRADE=0
INSTALL=0
;;
*)
echo "Aborting."
exit 4
;;
esac
# 更新、升级和安装软件
if [ $DNS_CONFIGURED = 1 ]; then
[ $UPDATE = 1 ] && chroot ${ROOT_DIR}/${DIST} /bin/bash -c "${UPDATE_CMD}"
[ $UPGRADE = 1 ] && chroot ${ROOT_DIR}/${DIST} /bin/bash -c "${UPGRADE_CMD}"
[ $INSTALL = 1 ] && chroot ${ROOT_DIR}/${DIST} /bin/bash -c "${INSTALL_CMD} vim"
else
echo "DNS not configured, skipping update and installation."
fi
# 清理
echo "Cleaning up"
rm ${FILE}
echo "Done."
echo "You can switch to ${DIST_FULLNAME} with \"chroot ${ROOT_DIR}/${DIST} /bin/bash\""11.2.3 参考文献
- Rocky Linux Documentation. Rocky Linux 9 Release Notes[EB/OL]. [2026-04-17]. https://docs.rockylinux.org/9/release_notes/. Rocky Linux 9 系列各版本的发行说明,9.7 代号 Blue Onyx。