chattr 手册中提到的 Linux 中的“项目 ID”是什么?

chattr 手册中提到的 Linux 中的“项目 ID”是什么?

chattr当我在我的 Linux 机器上阅读手册时( kali4-amd64),我在文件属性定义列表中看到了这一点:

A directory with the 'P' attribute set will enforce a hierarchical
structure for project id's.  This means that files and directory created in
the directory will inherit the project id of the directory, rename
operations are constrained so when a file or directory is moved into
another directory, that the project id's much match.  In addition, a hard
link to file can only be created when the project id for the file and the
destination directory match.

我个人不知道 Linux/UNIX 中的“项目 ID”是什么,而且谷歌搜索也没有找到任何结果,所以我希望这里有人能帮助我。

答案1

你问的是项目配额概念的一部分。项目配额是一种管理磁盘配额。特定文件系统类型可能支持或不支持项目 ID。让我们集中讨论 ext4 并从以下开始man 8 tune2fs

-O [^]feature[,...]
设置或清除文件系统中指示的文件系统功能(选项)。[…]

[…]

project
启用项目 ID 跟踪。这用于项目配额跟踪。

quota 启用内部文件系统配额 inode。

[…]

-Q quota-options
在超级块上设置“配额”功能并针对给定配额类型的配额文件进行操作。配额选项可以是以下一个或多个:

[^]usrquota
设置/清除超级块中的用户配额 inode。

[^]grpquota
设置/清除超级块中的组配额 inode。

[^]prjquota 设置/清除超级块中的项目配额 inode。

您可以在现有文件系统上启用这些选项:

tune2fs -O project,quota /your/device

(或者在创建新文件系统时提供它们mke2fs)。然后启用项目配额(如果您愿意,可以使用用户配额和/或组配额):

tune2fs -Q prjquota /your/device

安装它:

mount /your/device /the/mountpoint

setquota现在,您可以使用和等工具来管理配额quota(请注意,旧版本的工具可能缺少-P处理项目配额的选项)。传统上,您会限制用户或组可以使用的磁盘空间量。使用项目配额,您可以为“项目”执行此操作,无论参与的用户和组如何。

它的工作原理如下。首先将自己置于挂载点并创建几个目录:

cd /the/mountpoint
mkdir foo bar baz

启用其上的项目层次结构:

chattr +P foo bar baz

将它们分配给两个不同的项目:

chattr -p 123 foo       # 123 is an arbitrary number, project id
chattr -p 5 bar baz     # so is 5, the point is they are different

在以下位置创建文件:

echo "lorem ipsum" > foo/file1
echo "lorem ipsum" > bar/file2
echo "lorem ipsum" > baz/file3

现在调用:

lsattr -pR .

您将会看到如下几行:

  123 --------------e---P ./foo/file1
    5 --------------e---P ./bar/file2
    5 --------------e---P ./baz/file3

这意味着file1属于 id 为 的项目123file2并且file3属于 id 为 的项目5。如果您为这些项目定义配额(即限制项目可以使用的磁盘空间量),则每个文件都会影响其各自项目的配额消耗。

现在你引用的内容很有意义:

目录中创建的文件和目录将继承目录的项目 ID

在我们的示例中,file1从 继承了项目 ID foo。如果您在 中创建更多文件/目录,foo那么它们也将继承该 ID。这允许您(和其他用户)在其指定目录中处理项目,而您创建的文件将自动计入相应的配额。

仅当文件的项目 ID 与目标目录匹配时,才能创建文件的硬链接。

ln ./baz/file3 ./foo/会失败(尝试一下)但ln ./baz/file3 ./bar/会成功。操作系统不允许您轻易地将属于一个项目的文件(必须保持这种状态,因为源路径未取消链接)“嵌入”到另一个项目目录中。允许在其项目内链接文件。

当文件或目录移动到另一个目录时,项目 ID 必须匹配

我认为这有点误导。mv即使 id 不匹配也会完成其工作。关键是如果你调用

mv baz/file3 foo/

该工具将首先尝试将rename(2)文件移至新路径,这将失败(如上ln所示)。通常,或者在同一个项目中,它会成功,并且原始名称会消失。显然,这种行为就是“项目 ID 必须匹配”的意思。

mv不会立即退出。这就像在文件系统之间移动:mv重命名失败后,它会返回到复制+删除模式。实际上,它会创建一个复制(使用新的 inode 编号)在目标目录中。在我们的例子中,副本会继承 project id foo(就像此目录中的任何新文件一样),因此会影响 project 的配额消耗123。然后取消链接原始路径。这可能会影响 project 的配额消耗5;也可能不会:硬链接或打开文件描述符将导致原始 inode 和数据保留。

请注意,这有点令人惊讶:创建了一个新文件,旧的硬链接(如果有)没有链接到新文件,指向旧文件的文件描述符与新文件无关;就好像移动操作是在文件系统之间执行的一样。

有一种方法可以重mv命名而不是复制+删除。如果您手动将原始文件分配给目标项目

chattr -p 123 baz/file3

然后mv baz/file3 foo/才会真正移动它而不进行复制,也不会破坏硬链接(如果有的话)。但请注意,项目编号属于 inode(不是路径、不是名称、不是目录条目),因此chattr -p会影响所有硬链接。

因此,如果您需要移动一个大文件(即某些 inode 后面的数据,而不仅仅是众多硬链接之一)到另一个项目,则更改项目然后移动将节省不必要的复制。

相关内容