背景
我空间不足并/home/data
需要/home/data/repo
转至/home/data2
。
/home/data/repo
包含 1M 个目录,每个目录包含 11 个目录和 10 个文件。总计 2TB。
/home/data
在 ext3 上启用了 dir_index。
/home/data2
在 ext4 上。运行 CentOS 6.4。
我认为这些方法很慢,因为repo/
其下方有 100 万个目录。
尝试 1:mv
速度很快,但被打断了
如果这件事完成了,我就可以完成了:
/home/data> mv repo ../data2
但在传输了1.5TB之后就中断了。写入速度大约为1GB/分钟。
尝试 2:rsync
在构建文件列表 8 小时后进行爬取
/home/data> rsync --ignore-existing -rv repo ../data2
花了几个小时来建立“增量文件列表”,然后以 100MB/分钟的速度传输。
我取消它以尝试更快的方法。
尝试 3a:mv
抱怨
在子目录上测试它:
/home/data/repo> mv -f foobar ../../data2/repo/
mv: inter-device move failed: '(foobar)' to '../../data2/repo/foobar'; unable to remove target: Is a directory
我不确定这是关于什么的错误,但也许cp
可以帮助我摆脱困境。
尝试 3b:cp
8 小时后无果
/home/data> cp -nr repo ../data2
它读取磁盘 8 个小时,我决定取消它并返回 rsync。
尝试 4:rsync
在构建文件列表 8 小时后进行爬取
/home/data> rsync --ignore-existing --remove-source-files -rv repo ../data2
我以前--remove-source-files
认为如果我现在开始清理,可能会更快。
建立文件列表至少需要 6 个小时,然后以 100-200MB/分钟的速度传输。
但是服务器一夜之间负载过大,我的连接被关闭了。
尝试 5:只剩下 300GB 需要移动,为什么这么痛苦
/home/data> rsync --ignore-existing --remove-source-files -rvW repo ../data2
再次中断。这-W
似乎让“发送增量文件列表”变得更快,但在我看来这毫无意义。无论如何,传输速度非常慢,我放弃了这个。
尝试6:tar
/home/data> nohup tar cf - . |(cd ../data2; tar xvfk -)
基本上尝试重新复制所有内容,但忽略现有文件。它必须浏览 1.7TB 的现有文件,但至少它的读取速度为 1.2GB/分钟。
到目前为止,这是唯一能立即获得满足的命令。
更新:再次中断,不知何故,即使使用 nohup...
尝试 7:切腹
仍在讨论这个问题
尝试 8:脚本“合并”mv
目标目录有大约 120k 个空目录,因此我运行
/home/data2/repo> find . -type d -empty -exec rmdir {} \;
Ruby 脚本:
SRC = "/home/data/repo"
DEST = "/home/data2/repo"
`ls #{SRC} --color=never > lst1.tmp`
`ls #{DEST} --color=never > lst2.tmp`
`diff lst1.tmp lst2.tmp | grep '<' > /home/data/missing.tmp`
t = `cat /home/data/missing.tmp | wc -l`.to_i
puts "Todo: #{t}"
# Manually `mv` each missing directory
File.open('missing.tmp').each do |line|
dir = line.strip.gsub('< ', '')
puts `mv #{SRC}/#{dir} #{DEST}/`
end
完毕。
答案1
听说过将大任务拆分为较小的任务吗?
/home/data/repo 包含 1M 个目录,每个目录包含 11 个目录和 10 个文件。总计 2TB。
rsync -a /source/1/ /destination/1/
rsync -a /source/2/ /destination/2/
rsync -a /source/3/ /destination/3/
rsync -a /source/4/ /destination/4/
rsync -a /source/5/ /destination/5/
rsync -a /source/6/ /destination/6/
rsync -a /source/7/ /destination/7/
rsync -a /source/8/ /destination/8/
rsync -a /source/9/ /destination/9/
rsync -a /source/10/ /destination/10/
rsync -a /source/11/ /destination/11/
(...)
咖啡休息时间。
答案2
事情是这样的:
- 最初 rsync 将构建文件列表。
- 由于文件列表的初始排序,构建此列表非常慢。
- 可以通过使用 ls -f -1 并将其与 xargs 结合用于构建 rsync 将使用的文件集,或者将输出重定向到具有文件列表的文件来避免这种情况。
- 将此列表而不是文件夹传递给 rsync,将使 rsync 立即开始工作。
- 这篇文章完美地描述了对包含数百万个文件的文件夹使用 ls -f -1 的技巧:http://unixetc.co.uk/2012/05/20/large-directory-causes-ls-to-hang/
答案3
即使 rsync 很慢(为什么它很慢?也许 -z 会有所帮助)听起来你已经将很多内容移走了,所以你可以继续尝试:
如果您使用了--remove-source-files,那么您可以随后删除空目录。--remove-source-files 将删除所有文件,但将目录保留在那里。
只要确保你不要使用 --remove-source-files 与 --delete 进行多次传递。
另外为了提高速度,您可以使用--inplace
如果您因为尝试在服务器上远程执行此操作而被踢出,请继续在“屏幕”会话中运行此操作。至少这样您可以让它运行。
答案4
难道这不能通过结合使用 rsync 和 --inc-recursive 开关以及 cron 来实现吗?
即使是千兆位连接,移动 2 TB 也需要几个小时,没有任何开销。Rsync、mv 或 cp 都会给 I/O 增加不同程度的开销,尤其是在进行校验或其他验证时。
至少使用 --inc-recursive 开关,传输可以在文件列表仍在构建时开始。
我被告知 --inplace 可以提高速度并减少目标所需的空间,但会稍微降低文件完整性——如果不是这样的话,我很想知道。
如果随后使用适当的 rsync 设置(以及挂载远程卷所需的任何设置)创建了 cron 作业,则可以将其设置为最长运行 5:58h(使用 --stop-after=358),并且 cron 可以每 6 小时启动一次。这样,如果它随机停止,它将自动重新启动。--remove-source-files 可以与 rsync 一起使用,并且可以首先使用 find 来删除空的源目录(也许将 rsync 运行时间减少到 5:50h 以允许 find 遍历所有目录)。
我知道 rsync 的速度较慢(根据 OP),但在我看来,这样文件损坏的风险较低。
(坦白说 - 我仍在学习,所以如果我偏离了基础,请尽量温和地告诉我……)