# 11.2 Rocky Linux 兼容层

FreeBSD 通过 **emulators/linux-rl9** Port（内置 linux\_base-rl9）提供 Rocky Linux 9.7 兼容层。本节介绍安装步骤、版本验证及基础配置。

## 通过 FreeBSD Ports 安装 Rocky Linux 兼容层

### Rocky Linux 版本号概述

截至 2026 年 2 月 16 日，FreeBSD Ports 的 [emulators/linux-rl9](https://www.freshports.org/emulators/linux-rl9/)（其实际对应的基础包为 [emulators/linux\_base-rl9](https://www.freshports.org/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 (+)](https://github.com/freebsd/freebsd-ports/commit/3eb21a5228ef7b1c30886e17ad3f53b0066e1fa9)，真正决定版本号的是 Ports 框架中的 [Mk/Uses/linux.mk](https://github.com/freebsd/freebsd-ports/blob/main/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}"  # 如果都不是则直接打印报错信息
.  endif
```

### 启用 Linux 兼容层服务

安装 Rocky Linux 兼容层前，需先启用 Linux 兼容层服务。

启用 Linux 兼容层服务，并设置为开机自启：

```sh
# service linux enable
```

立即启动 Linux 兼容层服务:

```sh
# service linux start
```

### 安装基本系统

* 使用 pkg 安装：

```sh
# pkg install linux-rl9
```

* 也可使用 Ports 安装：

```sh
# cd /usr/ports/emulators/linux-rl9/
# make install clean
```

### 配置相关服务

安装完成后，还需配置相关服务。

```sh
# service dbus enable  # 通常桌面环境已经配置
# service dbus start  # 通常桌面环境已经配置
```

无需配置 **/etc/fstab** 文件，通过自动运行的 `linux_mounts_enable` 服务将挂载所需文件系统条目。

重启系统后生效。

## 通过 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\""
```

## 参考文献

* 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。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://book.bsdcn.org/di-11-zhang-linux-er-jin-zhi-jian-rong-ceng/di-11.2-jie-rocky-linux-jian-rong-ceng.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
