> For the complete documentation index, see [llms.txt](https://handbook.bsdcn.org/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://handbook.bsdcn.org/di-17-zhang-jail-yu-rong-qi/17.7.-linux-jail.md).

# 17.7.Linux jail

FreeBSD 可在 jail 内运行 Linux，利用 [Linux 二进制兼容性](/di-12-zhang-linux-er-jin-zhi-jian-rong-ceng/12.1.-gai-shu.md) 和 [sysutils/debootstrap](https://cgit.freebsd.org/ports/tree/sysutils/debootstrap/)。jail 没有内核，它们运行在宿主机的内核上。因此，需要在宿主系统中启用 Linux 二进制兼容性。

要在启动时启用 Linux ABI，执行以下命令：

```sh
# sysrc linux_enable="YES"
```

启用后，可执行以下命令在不重启的情况下启动它：

```sh
# service linux start
```

接下来，按照上述方法创建 jail，例如在 [使用 OpenZFS 快照创建瘦 jail](/di-17-zhang-jail-yu-rong-qi/17.5.-shou-jail.md) 中所示，但 **不做** 配置。FreeBSD Linux jails 需要特定的配置，接下来将详细说明。

如果宿主上尚不存在 **/etc/jail.conf**——例如在一个此前仅从命令行创建 jail 的系统上——创建一个空文件，以便 [service(8)](https://man.freebsd.org/cgi/man.cgi?query=service\&sektion=8\&format=html) 稍后可以停止该 jail：

```sh
# touch /etc/jail.conf
```

[service(8)](https://man.freebsd.org/cgi/man.cgi?query=service\&sektion=8\&format=html) jail 脚本在停止 jail 时会读取 **/etc/jail.conf**，因此如果该文件不存在，stop 命令会失败。如果前面章节中已经存在 **/etc/jail.conf**，则不需要此步骤。

以下 [jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html) 命令为 jail 执行所需配置并直接启动它，无需 **/etc/jail.conf** 条目。`-c` 标志创建新 jail，`-m` 修改已存在的 jail；合并为 `-cm` 时，[jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html) 在 jail 不存在时创建它，在存在时更新它：

```sh
# jail -cm \
    name=ubuntu \
    host.hostname="ubuntu.example.com" \
    path="/usr/local/jails/containers/ubuntu" \
    interface="em0" \
    ip4.addr="192.168.1.155" \
    exec.start="/bin/sh /etc/rc" \
    exec.stop="/bin/sh /etc/rc.shutdown" \
    mount.devfs \
    devfs_ruleset=4 \
    allow.mount \
    allow.mount.devfs \
    allow.mount.fdescfs \
    allow.mount.procfs \
    allow.mount.linprocfs \
    allow.mount.linsysfs \
    allow.mount.tmpfs \
    enforce_statfs=1
```

以 `root` 身份使用 [jexec(8)](https://man.freebsd.org/cgi/man.cgi?query=jexec\&sektion=8\&format=html) 访问新创建的 jail：

```sh
# jexec -u root ubuntu sh
```

在 jail 内，安装 [sysutils/debootstrap](https://cgit.freebsd.org/ports/tree/sysutils/debootstrap/) 并使用它在 **/compat/ubuntu** 下构建 Ubuntu 用户空间。[sysutils/debootstrap](https://cgit.freebsd.org/ports/tree/sysutils/debootstrap/) 是构建 Linux 用户空间的工具；之后进入 jail 并不需要它。首次运行 [pkg(7)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=7\&format=html) 会自动引导其安装：

```sh
# pkg install debootstrap
# debootstrap jammy /compat/ubuntu
```

`jammy` 选择 Ubuntu 22.04 LTS。也可选择更新的 LTS，例如 `noble`（Ubuntu 24.04），前提是它能在 linuxulator 下运行。

当进程完成并在控制台上显示 `Base system installed successfully` 信息时，从宿主系统停止 jail。由于此 jail 未在 **/etc/rc.conf** 中启用，也未在 **/etc/jail.conf** 中列出，因此使用带 `one` 前缀的 [service(8)](https://man.freebsd.org/cgi/man.cgi?query=service\&sektion=8\&format=html) 操作，该操作即使对未通过 `jail_enable` 启用或未在 `jail_list` 中列出的 jail 也会运行：

```sh
# service jail onestop ubuntu
```

`onestart` 和 `onestop` 操作是 `start` 和 `stop` 对于未通过 `jail_enable` 启用或未在 `jail_list` 中列出的 jail 的对应操作。

然后，在 **/etc/jail.conf** 中为 Linux jail 添加条目：

```sh
ubuntu {
  # 启动/日志记录
  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown";
  exec.consolelog = "/var/log/jail_console_${name}.log";

  # 权限
  allow.raw_sockets;
  exec.clean;
  mount.devfs;
  devfs_ruleset = 4;

  # 主机名/路径
  host.hostname = "${name}";
  path = "/usr/local/jails/containers/${name}";

  # 网络
  ip4.addr = 192.168.1.155;
  interface = em0;

  # 挂载
  mount += "devfs     $path/compat/ubuntu/dev     devfs     rw  0 0";
  mount += "tmpfs     $path/compat/ubuntu/dev/shm tmpfs     rw,size=1g,mode=1777  0 0";
  mount += "fdescfs   $path/compat/ubuntu/dev/fd  fdescfs   rw,linrdlnk 0 0";
  mount += "linprocfs $path/compat/ubuntu/proc    linprocfs rw  0 0";
  mount += "linsysfs  $path/compat/ubuntu/sys     linsysfs  rw  0 0";
  mount += "/tmp      $path/compat/ubuntu/tmp     nullfs    rw  0 0";
  mount += "/home     $path/compat/ubuntu/home    nullfs    rw  0 0";
}
```

> **技巧**
>
> jail 还可向其中运行的程序呈现特定的 Linux 内核标识。`linux` 参数选择 jail 是继承宿主的 Linux 模拟环境（`inherit`）还是获得自己的环境（`new`），`linux.osname`、`linux.osrelease` 和 `linux.oss_version` 分别设置 Linux 二进制文件看到的 OS 名称、发行版本和 OSS 版本。例如，设置 `linux.osrelease=6.1.0` 会使 jail 内的 [uname(1)](https://man.freebsd.org/cgi/man.cgi?query=uname\&sektion=1\&format=html) 和版本检查 Linux 程序报告该内核发行版本，而非宿主全局的 `compat.linux.osrelease` 值。

然后，使用以下命令像往常一样启动 jail：

```sh
# service jail start ubuntu
```

可使用以下命令访问 Ubuntu 环境：

```sh
# jexec ubuntu chroot /compat/ubuntu /bin/bash
```

更多信息，请参阅 [Linux 二进制兼容性](/di-12-zhang-linux-er-jin-zhi-jian-rong-ceng/12.1.-gai-shu.md)一章。
