# 20.11.磁盘配额

磁盘配额可用于限制用户或用户组在每个文件系统上可分配的磁盘空间或文件数量。这可以防止某个用户或用户组消耗掉所有可用的磁盘空间。

本节描述了如何为 UFS 文件系统配置磁盘配额。要在 ZFS 文件系统上配置配额，请参阅 [数据集、用户和组配额](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-zfs-quota)。

## 20.11.1. 启用磁盘配额

要确定 FreeBSD 内核是否提供对磁盘配额的支持，可以运行以下命令：

```sh
% sysctl kern.features.ufs_quota
kern.features.ufs_quota: 1
```

在这个例子中，`1` 表示启用了配额支持。如果值为 `0`，请在自定义内核配置文件中添加以下行，并按照 [配置 FreeBSD 内核](https://docs.freebsd.org/en/books/handbook/kernelconfig/#kernelconfig) 中的说明重新构建内核：

```ini
options QUOTA
```

接下来，在 **/etc/rc.conf** 中启用磁盘配额：

```ini
quota_enable="YES"
```

通常，在启动时，系统会通过 [quotacheck(8)](https://man.freebsd.org/cgi/man.cgi?query=quotacheck\&sektion=8\&format=html) 检查每个文件系统的配额完整性。此程序确保配额数据库中的数据正确反映文件系统中的数据。这是一个耗时的过程，会显著影响系统的启动时间。要跳过此步骤，可以在 **/etc/rc.conf** 中添加以下变量：

```ini
check_quotas="NO"
```

最后，编辑 **/etc/fstab** 文件，在每个文件系统的配置行中启用磁盘配额。要启用每个用户的配额，可以在文件系统的 **/etc/fstab** 配置行的选项字段中添加 `userquota`。例如：

```ini
/dev/da1s2g   /home    ufs rw,userquota 1 2
```

要启用组配额，请使用 `groupquota`。要启用用户和组配额，可以用逗号分隔选项：

```ini
/dev/da1s2g    /home    ufs rw,userquota,groupquota 1 2
```

默认情况下，配额文件存储在文件系统的根目录中，名为 **quota.user** 和 **quota.group**。有关更多信息，请参阅 [fstab(5)](https://man.freebsd.org/cgi/man.cgi?query=fstab\&sektion=5\&format=html)。不建议指定配额文件的替代位置。

配置完成后，重新启动系统，**/etc/rc** 将自动运行适当的命令，为 **/etc/fstab** 中启用的所有配额创建初始配额文件。

在正常操作过程中，通常无需手动运行 [quotacheck(8)](https://man.freebsd.org/cgi/man.cgi?query=quotacheck\&sektion=8\&format=html)、[quotaon(8)](https://man.freebsd.org/cgi/man.cgi?query=quotaon\&sektion=8\&format=html) 或 [quotaoff(8)](https://man.freebsd.org/cgi/man.cgi?query=quotaoff\&sektion=8\&format=html)。不过，建议阅读这些手册页，以了解它们的操作。

## 20.11.2. 设置配额限制

要验证配额是否已启用，可以运行以下命令：

```sh
# quota -v
```

这将显示每个启用了配额的文件系统的磁盘使用情况和当前的配额限制的摘要。

系统现在已准备好使用 `edquota` 设置配额限制。

有几个选项可以强制限制用户或组可以分配的磁盘空间数量，以及它们可以创建的文件数量。分配可以基于磁盘空间（块配额）、文件数量（inode 配额）或两者的组合进行限制。每个限制进一步细分为两个类别：硬限制和软限制。

硬限制是不可超过的。待用户达到硬限制，该用户在该文件系统上将无法再进行任何分配。例如，如果用户在文件系统上的硬限制为 500 KB，并且当前使用了 490 KB，则该用户只能分配额外的 10 KB。尝试分配额外的 11 KB 将失败。

软限制可以在一定时间内超出，称为宽限期，默认情况下为一周。如果用户超出了软限制并且宽限期已过，软限制将变为硬限制，并且不允许进一步的分配。当用户重新低于软限制时，宽限期将被重置。

在以下示例中，正在编辑 `test` 账户的配额。当调用 `edquota` 时，将打开由 `EDITOR` 指定的编辑器以编辑配额限制。默认编辑器是 vi。

```sh
# edquota -u test
Quotas for user test:
/usr: kbytes in use: 65, limits (soft = 50, hard = 75)
        inodes in use: 7, limits (soft = 50, hard = 60)
/usr/var: kbytes in use: 0, limits (soft = 50, hard = 75)
        inodes in use: 0, limits (soft = 50, hard = 60)
```

通常，每个启用了配额的文件系统会有两行。第一行表示块配额限制，第二行表示 inode 配额限制。可以更改这些值来修改配额限制。例如，要将 **/usr** 的块限制提高到软限制 `500` 和硬限制 `600`，请将该行的值更改为：

```sh
/usr: kbytes in use: 65, limits (soft = 500, hard = 600)
```

退出编辑器后，新配额限制将生效。

有时，可能希望在一系列用户上设置配额限制。可以通过首先为一个用户分配所需的配额限制来实现。然后，使用 `-p` 将该配额复制到指定范围的用户 ID（UID）。以下命令将为 UID `10000` 到 `19999` 的用户复制配额限制：

```sh
# edquota -p test 10000-19999
```

有关更多信息，请参阅 [edquota(8)](https://man.freebsd.org/cgi/man.cgi?query=edquota\&sektion=8\&format=html)。

## 20.11.3. 检查配额限制和磁盘使用情况

要检查单个用户或组的配额和磁盘使用情况，可以使用 [quota(1)](https://man.freebsd.org/cgi/man.cgi?query=quota\&sektion=1\&format=html)。用户只能检查自己的配额和自己所属组的配额。只有超级用户才能查看所有用户和组的配额。要获取启用了配额的文件系统的所有配额和磁盘使用情况的摘要，可以使用 [repquota(8)](https://man.freebsd.org/cgi/man.cgi?query=repquota\&sektion=8\&format=html)。

通常，用户未使用任何磁盘空间的文件系统不会出现在 `quota` 的输出中，即使该用户已为该文件系统分配了配额限制。可以使用 `-v` 来显示这些文件系统。以下是 `quota -v` 命令的示例输出，显示了一个用户在两个文件系统上的配额限制。

```sh
Disk quotas for user test (uid 1002):
     Filesystem  usage    quota   limit   grace   files   quota   limit   grace
           /usr      65*     50      75   5days       7      50      60
       /usr/var       0      50      75               0      50      60
```

在此示例中，用户当前在 **/usr** 上的软限制 50 KB 上超出了 15 KB，并且剩余 5 天的宽限期。星号 `*` 表示用户当前超出了配额限制。

## 20.11.4. NFS 上的配额

配额由 NFS 服务器上的配额子系统强制执行。[rpc.rquotad(8)](https://man.freebsd.org/cgi/man.cgi?query=rpc.rquotad\&sektion=8\&format=html) 守护进程将配额信息提供给 NFS 客户端上的 `quota`，允许这些机器上的用户查看他们的配额统计信息。

在 NFS 服务器上，通过取消 **/etc/inetd.conf** 文件中这一行的注释来启用 `rpc.rquotad`：

```ini
rquotad/1      dgram rpc/udp wait root /usr/libexec/rpc.rquotad rpc.rquotad
```

然后，重启 `inetd`：

```sh
# service inetd restart
```
