我想从服务器获取一些文件的备份。基本思路是使用创建一个存档tar
,将其保存到磁盘,然后下载。问题是剩余磁盘空间不足(或 tmpfs 的 RAM 不足),迫使我拆分存档并分块下载。
有没有一种简单的方法(例如,通过在管道从tar
到之间添加另一个命令split
)来split
在磁盘太满而无法写入下一块时暂停,并在磁盘再次可用时继续?(默认情况下,当由于磁盘已满而导致写入失败时,split 只会退出并显示错误消息。)
我想避免的替代方案:
- 通过 SSH 传输 tar 以将其直接保存在目标位置 - 当下载时间过长且下载客户端运行的是 Windows 时,连接可能会中断。
- 使用分割(或类似于创建多个 tar 档案)——我希望这将阻止我在下载档案之后将它们连接起来。
答案1
下面大部分快速而肮脏 sh
脚本旨在用作过滤器(在您的情况下为tar
和之间split
)。它是在 Ubuntu 中构建的,可能需要针对其他系统进行一些调整(例如,我不确定这是否column -t | cut -d " " -f 7
是无论操作系统如何解析的正确方法df
)。它需要/proc
。
将其保存为ensuredf
您的$PATH
指向的位置,使其可执行(chmod -x ensuredf
)并像这样使用:
… | ensuredf path requirement | …
在哪里
path
是您想要监控的目录;requirement
是所需的自由空间(df -B
必须理解这一点);
例子:
… | ensuredf /mnt/foo/data/ 2G | …
这个想法是让后台cat
将数据从stdin
(脚本的)传递到stdout
,但立即暂停。然后调用df
给定的path
,解析其输出并检查是否有比更多的空间requirement
。如果是,cat
则恢复,否则暂停。只要存在/proc
此条目,此操作就会以 1 秒的硬编码间隔循环cat
。
其他说明:
- 一些文件系统(尤其是 BTRFS)的输出
df
并不像您希望的那样精确; - 如果你的
tar
速度非常快,并且所需空间非常低,那么 1 秒的间隔可能太长了; - 但即使间隔为零,当可用空间低于时,在暂停
requirement
之前也会有一些延迟;cat
- 如果由于某种原因前台脚本延迟而后台
cat
运行良好,则磁盘可能仍会被填满。
这意味着你应该设置requirement
适当的安全裕度。使用此代码作为示例并根据你的需求进行调整。我设法编写了一个更安全的脚本,该脚本不断调用前台dd
来传递一块数据当且仅当有足够的磁盘空间,但是这些多个dd
进程比单个进程慢得多cat
。
#!/bin/sh
[ $# -eq 2 ] || { printf '%s\n' "usage: $0 path requirement" >&2 ; exit 1;}
pth="$1"
rqrmnt="$2"
intrvl=1
</proc/$$/fd/0 cat >/proc/$$/fd/1 &
kill -s STOP $!
while [ -d /proc/$! ] ; do
if [ $(df -P -B "$rqrmnt" "$pth" | tail -n 1 | column -t | cut -d " " -f 7) -ge 2 ]
then kill -s CONT $!
else kill -s STOP $!
fi
sleep "$intrvl"
done