我用来du
持续监控写入复制的 USB 驱动器的数据量。
我比较源驱动器和目标驱动器的磁盘使用情况并向用户显示复制进度。
问题是du
报告目标驱动器上存在 100% 的数据,即使我看到系统缓存中仍存在大量数据,驱动器的 LED 正在闪烁,并且驱动器尚未准备好移除。
我依次运行rsync
、sync
和umount
以确保数据确实存在,然后再让用户删除目标驱动器。sync
但是我无法监控进度。因此,在驱动器真正同步之前,用户将看到 100% 的情况。
我希望能够监控“真实”复制进度,因为这才是真正重要的 -rsync
在 25 秒内看到完全复制 1 GB 文件是没有用的,而我必须再等待 5 分钟才能sync
将其刷新到开车(我有点夸张,但你明白我的意思)。
这就是我rsync
循环监控每个驱动器的进度的方法:
PROGRESS="$(echo "$(du -s "/MEDIA/TARGET" 2>/dev/null | cut -f 1) / $(du -s "/MEDIA/SOURCE" 2>/dev/null | cut -f 1) " | bc -l)"
$PROGRESS
是 0 到 1 之间的浮点数,表示源驱动器使用率和目标驱动器使用率之间的比率。
我如何修改它,以便它只考虑已经同步到驱动器的数据,而不仅仅是在系统缓存中等待?
编辑:
我发现dd
可以执行省略系统缓存的写入。我做了一个测试,确实以这种方式复制文件可以du
报告实际值,并且我的进度指示最终会准确:
dd if=/media/SOURCE/file of=/media/TARGET/file bs=4M oflag=direct
这使用读取缓存,但禁用写入缓存,使进程更容易跟踪,而无需执行过多的读取。问题是,要使用dd
而不是rsync
我需要手动重新创建目录结构。我不需要关心文件属性或修改日期。
find
我想我可以使用,mkdir
和的组合dd
来首先重新创建目录树,然后逐个复制文件。我想知道 - 这种方法有什么缺点吗?
答案1
看起来处理这个问题的最好方法是使用直接文件输出。这样du
读数会更加准确。
不幸的是只dd
允许这样做,所以我们需要解决两个问题:
dd
不知道如何处理目录dd
一次只能复制一个文件
首先我们定义输入和输出目录:
SOURCE="/media/source-dir"
TARGET="/media/target-dir"
现在让我们cd
进入源目录,以便find
报告我们可以轻松操作的相对目录:
cd "$SOURCE"
将目录树从 复制$SOURCE
到$TARGET
find . -type d -exec mkdir -p "$TARGET{}" \;
重复文件以$SOURCE
忽略$TARGET
写入缓存(但利用读取缓存!)
find . -type f -exec dd if={} of="$TARGET{}" bs=8M oflag=direct \;
这不会保留文件修改时间、所有权和其他属性 - 但对我来说这没关系。