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

# 17.10.管理 jail

jail 创建完成后，可执行许多操作，如启动、重启或删除 jail、在其中安装软件等。本节将介绍可从主机对 jail 执行的不同操作。

## 17.10.1. 列出正在运行的 jail

要列出主机系统上正在运行的 jail，可使用 [jls(8)](https://man.freebsd.org/cgi/man.cgi?query=jls\&sektion=8\&format=html) 命令：

```sh
# jls
```

输出应该类似于以下内容：

```sh
   JID  IP Address      Hostname                      Path
     1  192.168.1.151  classic                       /usr/local/jails/containers/classic
```

[jls(8)](https://man.freebsd.org/cgi/man.cgi?query=jls\&sektion=8\&format=html) 支持 `--libxo` 参数，能通过 [libxo(3)](https://man.freebsd.org/cgi/man.cgi?query=libxo\&sektion=3\&format=html) 库以其他格式显示输出，例如 `JSON`、`HTML` 等。

例如，执行以下命令以获取 `JSON` 输出：

```sh
# jls --libxo=json
```

输出应该类似于如下内容：

```json
{"__version": "2", "jail-information": {"jail": [{"jid":1,"ipv4":"192.168.1.151","hostname":"classic","path":"/usr/local/jails/containers/classic"}]}}
```

默认列表只是 [jls(8)](https://man.freebsd.org/cgi/man.cgi?query=jls\&sektion=8\&format=html) 能报告内容的一小部分。加上 `-v` 标志可获取每个 jail 的详细多行摘要，包括其状态和分配的 cpuset ID：

```sh
# jls -v
```

使用 `-h` 可在所请求参数的值之上打印带字段名的标题行：

```sh
# jls -h jid name path
```

要查询单个 jail 的特定参数，用 `-j` 指定其名称并列出要打印的参数：

```sh
# jls -j classic path host.hostname ip4.addr
```

输出应该类似于以下内容：

```sh
/usr/local/jails/containers/classic classic 192.168.1.151
```

加上 `-d` 可包含正在关闭的 jail，否则它们在 dying 状态下会被隐藏：

```sh
# jls -d
```

## 17.10.2. 启动、重启和停止 jail

[service(8)](https://man.freebsd.org/cgi/man.cgi?query=service\&sektion=8\&format=html) 用于在主机上启动、重启或停止 jail。

例如，要启动 jail，运行以下命令：

```sh
# service jail start jailname
```

将 `start` 参数更改为 `restart` 或 `stop` 可对 jail 执行其他操作。

停止 jail 不止是杀掉其中的进程。当 jail 停止时，[jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html) 会先在 jail 内运行其 `exec.stop` 参数中的命令——通常是 `/bin/sh /etc/rc.shutdown`——以便其服务干净地关闭。然后向 jail 中仍在运行的进程发送 `SIGTERM`，并等待最多 `stop.timeout` 秒（默认为 10 秒）让它们退出。超时之后，jail 会被移除，并用 `SIGKILL` 杀掉剩余的一切。如果 `stop.timeout` 设置为零，则不会发送 `SIGTERM`，jail 会立即被移除。这正是运行慢停止守护进程的 jail 在停止时看似挂起十秒的原因；对于运行数据库或其他需要更长时间才能优雅关闭的服务的 jail，可在 **/etc/jail.conf** 中调高 `stop.timeout`。

## 17.10.3. 销毁 jail

销毁 jail 不是像使用 [service(8)](https://man.freebsd.org/cgi/man.cgi?query=service\&sektion=8\&format=html) 停止 jail 并删除 jail 目录和 **/etc/jail.conf** 条目那么简单。

FreeBSD 非常重视系统安全。因此，某些文件即使是 root 用户也不能删除。这种功能称为文件标志（File Flags）。对于文件存储在 UFS 文件系统上的 jail，必须先清除这些标志才能删除 jail 目录。

第一步是停止所需的 jail，执行以下命令：

```sh
# service jail stop classic
```

第二步是使用 [chflags(1)](https://man.freebsd.org/cgi/man.cgi?query=chflags\&sektion=1\&format=html) 移除这些标志，执行以下命令，其中 `classic` 是要删除的 jail 名称：

```sh
# chflags -R 0 /usr/local/jails/containers/classic
```

第三步是删除包含 jail 的目录：

```sh
# rm -rf /usr/local/jails/containers/classic
```

以上两步适用于存储在 UFS 文件系统上的 jail。如果 jail 由其专用的 ZFS 数据集支撑——如 [设置 jail 目录结构](/handbook/di-17-zhang-jail-yu-rong-qi/17.3.-zhu-ji-pei-zhi-jail.md) 中所创建——则改为销毁数据集来移除。数据集销毁不受文件标志阻挡，因此此时不需要 [chflags(1)](https://man.freebsd.org/cgi/man.cgi?query=chflags\&sektion=1\&format=html) 这一步：

```sh
# service jail stop classic
# zfs destroy zroot/jails/containers/classic
```

加上 `-r` 可同时销毁数据集持有的所有快照。

> **注意**
>
> 通过克隆模板快照创建的 ZFS 瘦 jail（参见 [瘦 jail](/handbook/di-17-zhang-jail-yu-rong-qi/17.2.-jail-de-lei-xing.md)）依赖于该快照。只要还有克隆存在，[zfs(8)](https://man.freebsd.org/cgi/man.cgi?query=zfs\&sektion=8\&format=html) 就会拒绝销毁模板快照，并打印依赖它的克隆列表。要退役一个模板，请先销毁从它克隆出的每个 jail，或对某个克隆执行 `zfs promote` 使其不再依赖模板。

最后，无论哪种情况，都需删除 **/etc/jail.conf** 或 **/etc/jail.conf.d** 中的 jail 条目。对于 NullFS 瘦 jail，还要删除其 **.fstab** 文件和现已为空的挂载点目录。

## 17.10.4. 在 jail 中处理软件包

[pkg(8)](https://man.freebsd.org/cgi/man.cgi?query=pkg\&sektion=8\&format=html) 工具支持 `-j` 参数，用于处理安装在 jail 中的软件包。

例如，要在 jail 中安装 [www/nginx-lite](https://cgit.freebsd.org/ports/tree/www/nginx-lite/)，可**从主机**执行以下命令：

```sh
# pkg -j classic install nginx-lite
```

有关在 FreeBSD 中使用软件包的更多信息，请参见 [安装应用程序：软件包和 Ports](/handbook/di-4-zhang-an-zhuang-ying-yong-cheng-xu-ruan-jian-bao-he-ports/4.1.-gai-shu.md)。

## 17.10.5. 从主机管理 jail 中的服务

jail 中的服务可从主机启用和控制，无需先用 [jexec(8)](https://man.freebsd.org/cgi/man.cgi?query=jexec\&sektion=8\&format=html) 进入 jail。[service(8)](https://man.freebsd.org/cgi/man.cgi?query=service\&sektion=8\&format=html) 和 [sysrc(8)](https://man.freebsd.org/cgi/man.cgi?query=sysrc\&sektion=8\&format=html) 都接受 `-j` 参数，通过 ID 或名称指定目标 jail，并作用于该 jail 的 [rc(8)](https://man.freebsd.org/cgi/man.cgi?query=rc\&sektion=8\&format=html) 配置。

延续上面的软件包示例，直接从主机在 `classic` jail 中启用并启动 nginx：

```sh
# sysrc -j classic nginx_enable=YES
# service -j classic nginx start
```

这些命令的效果与通过 [jexec(8)](https://man.freebsd.org/cgi/man.cgi?query=jexec\&sektion=8\&format=html) 运行 [sysrc(8)](https://man.freebsd.org/cgi/man.cgi?query=sysrc\&sektion=8\&format=html) 和 [service(8)](https://man.freebsd.org/cgi/man.cgi?query=service\&sektion=8\&format=html) 相同，但它们让主机端的管理和脚本与非 jail 系统保持一致。

## 17.10.6. 访问 jail

虽然前面提到最好从主机系统管理 jail，但可使用 [jexec(8)](https://man.freebsd.org/cgi/man.cgi?query=jexec\&sektion=8\&format=html) 进入 jail。

可从主机系统执行 [jexec(8)](https://man.freebsd.org/cgi/man.cgi?query=jexec\&sektion=8\&format=html) 命令来进入 jail：

```sh
# jexec -u root jailname
```

`-u` 标志选择以哪个用户身份运行，并针对*主机*的密码数据库解析名称。若要针对 *jail 自己的*密码数据库解析用户，请使用 `-U`。当未给定命令时（如这里），[jexec(8)](https://man.freebsd.org/cgi/man.cgi?query=jexec\&sektion=8\&format=html) 会启动该用户在 jail 内的登录 shell。加上 `-l` 可在干净的登录环境中运行，仅保留 `HOME`、`SHELL`、`TERM` 和 `USER`，将 `PATH` 重置为 **/bin:/usr/bin**，行为如同全新登录；`-d` 设置工作目录，默认为 jail 根目录。

当进入 jail 时，系统将显示在 [motd(5)](https://man.freebsd.org/cgi/man.cgi?query=motd\&sektion=5\&format=html) 中配置的消息。

## 17.10.7. 在 jail 中执行命令

要从主机系统在 jail 中执行命令，可使用 [jexec(8)](https://man.freebsd.org/cgi/man.cgi?query=jexec\&sektion=8\&format=html)。

例如，要停止在 jail 中运行的服务，可执行以下命令：

```sh
# jexec -l jailname service nginx stop
```

## 17.10.8. 从主机查看 jail 中的进程和套接字

从主机上，每个 jail 的进程和套接字都是可见的，并可按 jail 过滤。

[ps(1)](https://man.freebsd.org/cgi/man.cgi?query=ps\&sektion=1\&format=html) 接受 `-J` 将输出限制为单个 jail，按 JID 或名称指定：

```sh
# ps -J classic
```

输出应该类似于以下内容，其中 `STAT` 列中的 `J` 标记表示进程在 jail 中运行：

```sh
 PID TT  STAT    TIME COMMAND
2841  -  IsJ  0:00.02 /usr/sbin/syslogd -ss
2903  -  IsJ  0:00.00 nginx: master process /usr/local/sbin/nginx
```

使用 `ps -J 0` 可仅显示主机自己的进程。还可在 `-o` 输出格式中加入 `jail` 和 `jid` 关键字，以显示每个进程所属的 jail。例如，列出主机上的每个进程及其所属 jail：

```sh
# ps ax -o pid,jail,command
```

[top(1)](https://man.freebsd.org/cgi/man.cgi?query=top\&sektion=1\&format=html) 接受 `-J` 将其实时显示过滤为单个 jail，这会隐含启用 `-j` 并添加 `JID` 列：

```sh
# top -J classic
```

[sockstat(1)](https://man.freebsd.org/cgi/man.cgi?query=sockstat\&sektion=1\&format=html) 用 `-j` 列出属于某个 jail 的套接字，这是检查 jail 中的守护进程在启动服务后实际绑定了哪些端口的自然方式：

```sh
# sockstat -4 -6 -l -j classic
```

从 jail 内部情况正好相反：jail 中的进程只能看到自己 jail 的进程和套接字，永远看不到主机或其他 jail 的。

## 17.10.9. 使用 jail 工具直接管理 jail

上面所示的 [service(8)](https://man.freebsd.org/cgi/man.cgi?query=service\&sektion=8\&format=html) 包装器是开机时运行 jail 的常规方式，但 [jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html) 也可直接创建、修改和移除 jail，这对于脚本编写以及在不依赖 rc 框架的情况下测试配置很有用。

按名称创建已配置的 jail：

```sh
# jail -c classic
```

移除正在运行的 jail；这同时会移除它创建的任何子 jail 并杀掉其中的进程：

```sh
# jail -r classic
```

`-m` 标志可在不重启的情况下修改正在运行的 jail 的参数。例如，向正在运行的 jail 添加第二个 IPv4 地址：

```sh
# jail -m name=classic ip4.addr+=192.168.250.71
```

[jail(8)](https://man.freebsd.org/cgi/man.cgi?query=jail\&sektion=8\&format=html) 指出“某些参数不能在正在运行的 jail 上更改”；实际中这包括 `path` 和 `vnet`，它们要求重启 jail。

最后，`-e` 可展示所有已配置的非通配符 jail 及其参数，而不会创建、修改或移除任何内容，便于验证配置文件。它接受一个用于分隔参数的字符串：

```sh
# jail -e ,
```

## 17.10.10. 备份和迁移 jail

jail 在很大程度上是自包含的，因此备份或迁移到另一台主机主要就是复制其文件和配置。

先停止 jail 以获得一致的副本；基于 ZFS 的 jail 可在运行时直接快照。对于位于其专用 ZFS 数据集上的 jail，可递归快照并流式传输到目标主机：

```sh
# service jail stop classic
# zfs snapshot -r zroot/jails/containers/classic@migrate
# zfs send -R zroot/jails/containers/classic@migrate | ssh newhost zfs receive zroot/jails/containers/classic
```

[zfs-send(8)](https://man.freebsd.org/cgi/man.cgi?query=zfs-send\&sektion=8\&format=html) 和 [zfs-receive(8)](https://man.freebsd.org/cgi/man.cgi?query=zfs-receive\&sektion=8\&format=html) 的完整机制（包括增量传输）在 [复制](/handbook/di-23-zhang-z-wen-jian-xi-tong-zfs/23.4.-zfs-guan-li.md) 中说明。

对于位于 UFS 文件系统上的 jail，使用 [tar(1)](https://man.freebsd.org/cgi/man.cgi?query=tar\&sektion=1\&format=html) 加 `-p` 以保留所有权、权限和文件标志：

```sh
# tar -cpf classic.tar -C /usr/local/jails/containers classic
```

在目标主机上以 `root` 身份用 `tar -xpf` 解压归档，以保留文件标志。当 jail 占用其专用的 UFS 文件系统时，[dump(8)](https://man.freebsd.org/cgi/man.cgi?query=dump\&sektion=8\&format=html) 和 [restore(8)](https://man.freebsd.org/cgi/man.cgi?query=restore\&sektion=8\&format=html) 是替代方案；它们作用于整个文件系统，因此不适用于本章使用的布局——所有 jail 都是同一共享文件系统内的目录。

最后，将 jail 在 **/etc/jail.conf** 中的块——或它在 **/etc/jail.conf.d** 中的文件——复制到新主机，调整任何主机相关的参数（如 `interface`、`ip4.addr` 或 VNET jail 使用的网桥），然后在新主机上启动 jail。

> **警告**
>
> 目标主机运行的 FreeBSD 发行版本不能比 jail 的用户空间旧，遵循与 jail 永远不能运行比宿主更新版本相同的规则。NullFS 瘦 jail 不是自包含的：其模板和骨架也必须存在于目标主机上，因此需一并迁移，或先将 jail 转换为厚拷贝。**/etc/rctl.conf** 中保存的任何 [rctl(8)](https://man.freebsd.org/cgi/man.cgi?query=rctl\&sektion=8\&format=html) 规则必须单独带过去。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://book.bsdcn.org/handbook/di-17-zhang-jail-yu-rong-qi/17.10.-guan-li-jail.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
