我有一个包含每日快照文件夹的备份。为了节省空间,不同快照中的相同文件通过硬链接(由 rsync 生成)进行重复数据删除。
当空间不足时,一种选择是删除旧快照。但是由于硬链接,很难计算出删除给定快照会获得多少空间。
我能想到的一个选择是du -s
首先在所有快照文件夹上使用,然后在除了我可能删除的文件夹之外的所有文件夹上使用,并且差异会给我预期的获得空间。但是,这非常麻烦,并且在我试图找到合适的快照进行删除时必须重复进行。
有没有更简单的方法?
在尝试并思考Stéphane Chazelas和derobert的答案后,我意识到我的问题不够精确。这是更精确的尝试:
我有一组目录(“快照”),其中包含与另一个快照中的文件部分存储相同(硬链接)的文件。我正在寻找一种解决方案,该解决方案可为我提供快照列表以及其中文件占用的每个已用磁盘存储量,但没有该存储也被另一个快照中的文件使用。我想允许每个快照中存在硬链接的可能性。
我的想法是我可以查看该列表来决定当我用完空间时我应该删除哪些快照,这是在删除获得的存储空间和快照的价值(例如基于年龄)之间的权衡。
您可以使用 GNU 手动完成
find
:这计算了在找到快照目录中找到的所有链接后链接计数将下降到 0 的文件的磁盘使用情况。
find
印刷:1 <disk-usage>
对于目录<link-count> <disk-usage> <inode-number>
对于其他类型的文件。我们假装目录的链接计数总是一个,因为实际上它不是,这是因为
..
条目,并且find
没有列出这些条目,目录通常没有其他硬链接。从该输出中,
awk
计算链接计数为 1 的条目的磁盘使用情况以及它看到的 inode 的磁盘使用情况<link-count>
(即所有硬链接都在当前目录中的 inode,就像那些带有链接的 inode 一样) -count of one 将在删除目录树后回收其空间)。您还可以使用它
find snapshot-dir1 snapshot-dir2
来找出如果两个目录都被删除将回收多少磁盘空间(如果在两个目录中都找到了文件并且仅在那些快照)。如果你想知道每次删除快照目录后你会节省多少空间(以累积的方式),你可以这样做:
它按词法顺序处理快照列表。如果您以不同的顺序处理它,那可能会给您不同的数字,除了最后一个(当所有快照都被删除时)。
请参见
numfmt
使数字更具可读性。假设所有文件都在同一个文件系统上。如果没有,您可以替换
%i
为%D:%i
(如果它们不在同一个文件系统上,那将意味着您在那里有一个无论如何都无法删除的挂载点)。如果您的文件名不包含模式字符或换行符,您可以使用
find
+du
的排除功能来执行此操作:该
find
位获取-type f
硬链接计数大于 1 ( ) 的所有文件 (-links +1
)。打印出cut
领先发现的修剪。./
然后du
询问每个目录的磁盘使用情况,不包括具有多个链接的所有文件。当然,一旦您删除快照,现在可能只有一个链接的文件以前有两个 - 所以每删除几次,您真的应该重新运行它。如果它需要使用任意文件名,它需要更多的脚本来替换
du
(那些是 shell 模式,所以转义是不可能的)。此外,正如 Stéphane Chazelas 指出的那样,如果一个快照中存在硬链接(文件的所有名称都位于单个快照中,而不是快照之间的硬链接),这些文件将被排除在总数之外(即使删除快照会恢复那个空间)。
自从我写下这个答案以来,Stéphane Chazelas 一直让我相信他的答案是正确的。我留下了我的答案,包括代码,因为它也能很好地工作,并提供一些漂亮的打印。它的输出如下所示:
由于我对这两个答案中的任何一个都不是 100% 满意(截至 2018 年 11 月 18 日)——尽管我从他们两个那里学到了东西——我创建了自己的工具并在此处发布。
类似于Stéphane Chazelas的回答,它用于
find
获取 inode 列表和相关文件/目录大小,但不依赖于“最多一个链接”启发式。相反,它为每个输入目录创建一个唯一的索引节点列表(不是文件/目录!),从其他目录中过滤掉索引节点,然后将剩余的索引节点大小相加。这样它就可以解释每个输入目录中可能存在的硬链接。作为副作用,它忽略了来自输入目录集之外的可能的硬链接。使用的 bash 外部工具:
find
,xargs
,mktemp
,sort
,tput
,awk
,tr
,numfmt
,touch
,cat
,comm
,rm
. 我知道,它不完全是轻量级的,但它完全符合我的要求。我在这里分享它以防其他人有类似的需求。如果有什么可以做得更高效或更简单的,欢迎评论!我不是 bash 大师。
要使用它,请将以下代码保存到脚本文件
duu.sh
中。第一个注释块中包含简短的使用说明。