我没有意识到这会如此困难。我只是用焦油。我有两部分数据,一个是大量的 pcap 数据有效负载,另一个是 python pickled 文件形式的一些附加元数据。我的目标是创建一个包含这两个文件的 .tar 文件,并使用 XZ 进行压缩。
我希望能够对 tarball 建立索引,以便可以从 .tar.xz 文件中快速提取元数据文件。我使用 PIXZ 进行 xz 压缩,它会自动索引 tar 文件。因为我正在压缩的 pcap 数据太大,所以在压缩之前我不想接触磁盘。我正在使用 tcprewrite 对它进行其他一些更改,但这些并不重要。
我已将所有工具设置为使用命名管道,它很漂亮而且非常快。不幸的问题是 tar 不能与命名管道一起使用。每次我尝试压缩命名管道时,它只会将 /dev/fd/#numbers 写入 tarball 中。我不能只是将 pcap 数据写入磁盘或 /dev/shm 来对其进行 tar,重要的是 pcap 数据在压缩之前不会到达磁盘。
我正在用 python 编写整个实用程序,因此我尝试使用 python 的 tarfile 模块。该文档声称它适用于 FIFO,但是当我使用 tarfile.add() 时,我遇到了同样的问题。我尝试过研究像 zip 这样的替代方案(它有一个用于使用命名管道的 -FI 选项),但我需要对我们现有的基础设施使用 tar。
我尝试了 gnutar 和 bsdtar,但它们都不能与管道一起使用。只要最终结果是一个已编入索引并允许快速访问元数据的 .tar.xz 文件,最终使用什么工具并不重要。
答案1
不要为此感到沮丧...我相信您会设法解决这个问题!
我认为 tar 让你困惑的是,“支持命名管道”意味着它可以识别命名管道并存储它们作为命名管道在存档中,以便您稍后可以再次将它们恢复为命名管道...这并不是您真正想要的。
此外,tar 文件的格式不太适合您正在做的事情,因为描述文件的条目存储在其内容之前,并且文件条目必须包含文件大小,因此除非您事先知道内容的确切大小,很难做到这一点...
有这个解决方案(参见 TarFileStdin),它使用 hack 来解决这个问题。它插入文件大小为零的 TarInfo,然后存储文件的内容,最后查找原始 TarInfo 的偏移量并用正确的大小覆盖它......这有点太 hacky,但它应该可以工作......但请继续阅读。
您提到“我希望能够对 tarball 建立索引,以便我可以从 .tar.xz 文件中快速提取元数据文件”,这样看起来更像是一个 ZIP 文件! ZIP 格式首先存储所有文件的内容,然后在 ZIP 末尾存储文件信息和偏移量表。从这个意义上说,它是索引的,就像你提到的那样。列出 ZIP 的内容可以很快完成,因为工具可以轻松地从文件末尾开始找到该文件表。
您可以使用 ZIP 的本机压缩格式,也可以仅使用 ZIP 的“存储”模式(未压缩),然后在其中添加 xyz.pcap.xz 文件。将 *.xz 文件添加到 ZIP 中可以方便地使用外部压缩器,例如并行 xz。
Python 3 的zipfile.ZipFile
对象有一个open()
方法它允许您仅按名称添加文件并接收可以写入内容的文件对象。
您可以使用该 API 并将shutil.copyfileobj()
压缩的 pcap 从命名管道添加到 ZIP 文件:
import shutil
import zipfile
with zipfile.ZipFile('mydata.zip', 'w') as zf:
with zf.open('xyz.pcap.xz', 'w') as outputf:
with open('/path/to/namedpipe', 'r') as inputf:
shutil.copyfileobj(inputf, outputf)
zf.write('metadata.pickle') # from local directory
此代码片段假设您正在将已 xz 压缩的 pcap 数据写入命名管道,并且元数据已序列化到当前目录中名为“metadata.pickle”的文件中。 (当然,您open()
也可以使用 ZipFile 将 pickle 元数据直接序列化到 ZIP 文件中的条目中!)
如果你想使用 zipfile 的本机压缩,你可以为 ZipFile 设置默认压缩:
with zipfile.ZipFile('mydata.zip', 'w', zipfile.ZIP_LZMA) as zf:
(默认值为 ZIP_STORED,这意味着不压缩,如果您要在那里传输 xz 压缩的数据,这可能就是您想要的。)
请参阅zip 文件的文档更多细节。较新的 Python 具有更多功能,例如使用 Python 3.5,您实际上可以将 zip 文件写入管道,这样您就可以通过 SSH 将其直接上传到远程主机。
希望这个对你有帮助!如果您确实需要 tarball,请尝试这个答案,但我确实认为使用 Python 3 的 zipfile 解决方案对于您描述的用例来说是更好的方法!因此,如果这种格式可行,我真的会推荐它。