最近,我启动了cp
创建大目录备份的命令。所以,我使用了这样的命令:
cp -rv big_directory new_location
因为文件很大,所以执行这个命令花了很长时间,我也想看看复制的进度。所以我还在du
另一个终端中使用了该命令,如下所示:
du -sh new_location/*
但这个命令执行起来也需要很长时间。特别是如果该目录中有大文件。
假设cp
执行该命令需要 10 分钟。如果我du
在启动命令 1 分钟后启动该cp
命令,并假设du
需要 1 分钟才能执行,我想知道我是否可以信任du
?的输出
它是否为我提供了启动时 (t=1min) 情况的可靠输出du
,或者是否为我提供了执行时间结束时du
(t=2min) 情况的输出?显然,由于复制,目录的大小在命令new_location
开始和结束之间发生了变化。du
答案1
@derobert 解释了如何du
运作。
他没有提到,除非您有绝对大量的小文件/目录(因此元数据需要大量内存),否则du
立即再次运行通常会更快地产生结果。
一个大文件并不会使du
速度变慢,但复制它更有可能将目录缓存挤出内存。 (桌面响应能力可以提高通过设置vm.swappiness=10
,并使用 sysctl 设置将元数据优先于数据vm.vfs_cache_pressure=60
(将它们放入/etc/sysctl.d/99-local
.)
当多个进程同时访问文件系统时,每个系统调用都会获取运行时状态快照的信息。例如,进程可能会检查文件是否存在,然后尝试打开它,却发现它不再存在。因为在检查之间的时间间隔内另一个进程已重命名/删除了它。 (当这导致问题/是错误的根源时,称为竞争条件。)
如果 的目录遍历顺序du
与选择的顺序相同cp
,则du
直到运行时接近结束时才会到达仍在修改的目录,因此不会错过太多时间结束了。 OTOH,如果首先对放置新文件du
的目录求和cp
,然后再花一分钟对其余的求和,结果将是陈旧的。
答案2
du
通过递归扫描目录来工作,计算所有文件和目录的大小。就像是:
- 从命令行上给出的第一个目录开始。
stat
目录以确定其大小,并将其添加到总数中- 从目录中读取第一个条目(文件或子目录名称)
- 如果它是一个文件,
stat
则将其添加到总数中 - 如果它是一个目录(当然不是
.
和..
),则对子目录执行步骤 2-7 - 如果还有另一个条目,请阅读它并返回到 4 [您可能想知道:如果在扫描单个目录
cp
时添加另一个条目会发生什么?du
这标准说它可能会或可能不会出现——未指定。] - 打印出目录大小
如果目录和文件像du
所有这些一样发生变化(就像您的情况一样),那么它给出的大小不是从头到尾的大小,而是介于两者之间的大小 - 但不完全是。不过可能已经足够接近了,至少对于cp
.
要获取进度指示器,除了 @roaima 的rsync
建议之外,还有cp -v
, gcp
(通过快速搜索找到)和复杂的东西,例如(cd /src && tar c .) | pv -pterb -s $(du -sb /src) | (cd /dst && tar x)
.
答案3
如果您已经rsync
安装,您可以像这样查看复制进度
rsync -vP big_directory new_location
如果您想保留权限、时间戳、所有权等,您可以将标志添加-a
到rsync
或 将-p
标志添加到cp
。
这个答案回避了使用 的du
假设,即您实际上想观察复制的进度,而不是查看所用磁盘空间的近似值。