我有一些大文件,这些文件是动态生成到标准输出的,每 24 小时生成一个。我想将这些文件逐步存档在磁带上,最好是在可能跨越多个磁带的单个存档中。
Tar 非常适合管理磁带,因为它具有附加到存档和加载下一个磁带的内置功能。但它在接受来自标准输入的数据方面非常差。无论我做什么,它最终都会将一个特殊文件(链接或命名管道)写入存档,而不是其内容。
这是我一直在尝试的示例命令。第一天,生成一个新的存档:
ln -s /dev/stdin day1 # or use the --transform option of tar
data_generator | tar -c -h -M -f /dev/nst0 -H posix -F 'mtx -f /dev/sch0 next' day1
第二天,我想将 -c 更改为 -A 并将新流保存到附加到 tar 存档的新文件中,在必要时加载新磁带。
data_generator | tar -A -h -M -f /dev/nst0 -H posix -F 'mtx -f /dev/sch0 next' day2
正如我所说,我在存档中找到的只是命名管道(带 -h)或符号链接(不带 -h)。
我尝试过的一些想法并不好:
- 使用
split
代替tar
是不可行的,因为它太基础了。它只能分割到预定义的维度(如果我不从磁带的开头开始就不好),并且它无法将不同的日期连接到可解压的存档中。 Tar 不需要知道数据或磁带的大小,它只会在出现写入错误时切换到新磁带。 - 我读过cpio、star和dar的手册。我不认为它们比焦油更好地处理管道。
感谢您的任何提示。
编辑:我开始认为 tar 是不可能的,因为它需要在开始写入之前知道文件的大小。事实上,对于一个可以扩展的档案,如果你在内容之前写了大小,那么追加是非常棘手的。
答案1
经过一晚的休息,我发现如果提前知道要读取的数据量(我知道),只需一点Python就可以完成此操作。这个简单的程序从 stdin 读取 1MB 数据,并将数据封装为“filename.dat”的 tar 存档写入 stdout。
#!/usr/bin/env python3
import tarfile
with open("/dev/stdout", "ab") as outf:
tar = tarfile.open(fileobj=outf, mode="w")
with open("/dev/stdin", "rb") as inf:
filesize=1048576 # 1MB
tarinfo = tarfile.TarInfo(name="filename.dat")
tarinfo.size=filesize
tar.addfile(tarinfo, fileobj=inf)
# -- end program tarpipe.py ---
例如,您可以获得 1MB 的随机数据,并通过此程序将其传输到 tar 存档:
cat /dev/urandom |./tarpipe.py > daily.tar
生成的存档包含一个名为“filename.dat”的 1MB 文件。
由于 tar 档案的工作原理,只要每次修改文件名(否则文件在解压时将相互覆盖),您就可以继续附加 (>>) 来扩展它。
为了管理磁带更换,我可以通过 mbuffer 传输输出,mbuffer 可以在本地完成此操作。