磁盘已满时暂停 tar|split

磁盘已满时暂停 tar|split

我想从服务器获取一些文件的备份。基本思路是使用创建一个存档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

相关内容