我正在将一个大型文件集从具有较高_PC_LINK_MAX
(每个 inode 的最大硬链接数)的文件系统转换为较低的文件系统。
特别是,我正在使用 Amazon EFS,它的最大值为 175,如上所述这里。
因此,我希望输入是一组经过重新调整的链接数高达 250 的文件,以便 inode 被拆分,这样每个文件的最大链接数为 100 个。
是否有一种巧妙的调用hardlink
可以做到这一点?或者也许有一个选项rsync -aH
或可能cp -a
有帮助?
...否则,一些黑客行为是有序的...
答案1
情况很棘手。想象一下最大链接是 5 个,并且您有 12 个文件
a01
全部a12
硬链接在一起。您需要拆分a01..a05
和a06..a10
,a11..a12
其中a06
和a07
等仍然硬链接在一起,但不是a01
。
这是一个 bash 脚本,rsync
它在我的系统上的示例源目录 ( src=/usr/libexec/git-core/
) 上运行,该目录有 110 个硬链接。它通过该函数模拟max
目标目录中最多 50 个 links( ) 。在真实的情况下,你会忽略realdest
sim
链接太多错误,并且不使用该功能。
rsync -ni
在初始正常 rsync (有错误)之后,通过使用将函数中的文件名提取calctodo
到 中来创建丢失文件的列表/tmp/todo
。
然后有一个循环rsync
,我们再次忽略丢失的文件链接太多2*175
错误(如果原始目录中有多个链接,则会出现错误)。成功创建的文件之间是硬链接的。计算出新的丢失文件列表。重复此操作,直到没有更多文件为止。
src=/usr/libexec/git-core/
realdest=/tmp/realdest
#rm -fr "$realdest"
max=50
sim(){
find ${1?} -links +$max |
sed "1,${max}d" |
xargs --no-run-if-empty rm
}
calctodo(){
sed -n '/^hf/{ s/[^ ]* //; s/ =>.*//; p }' >/tmp/todo
}
rsync -aHR "$src" "$realdest"; sim "$realdest"
rsync -niaHR "$src" "$realdest" | calctodo
while [ -s /tmp/todo ]
do mv /tmp/todo /tmp/todo.old
rsync -aHR --files-from=/tmp/todo.old / "$realdest"; sim "$realdest"
rsync -niaHR --files-from=/tmp/todo.old / "$realdest" | calctodo
done
如果您的文件名带有“=>”、换行符等,您可能需要修改此设置。
请注意,您可以通过以下方式找到文件系统支持的最大链接数:
getconf LINK_MAX /some/directory