tarまたはPythonのtarfileモジュールを使用して名前付きパイプからtarballを作成する

tarまたはPythonのtarfileモジュールを使用して名前付きパイプからtarballを作成する

それがそんなに難しいとは知りませんでした。私はただタールを使います。 2つのデータがあります。 1つは大規模なpcapデータペイロード、もう1つはPythonピクチャファイルの形式の追加のメタデータです。私の目標は、これら2つのファイルを含む.tarファイルを作成し、XZを使用して圧縮することです。

.tar.xzファイルからメタデータファイルをすばやく抽出できるように、tarballをインデックス化できるようにしたいです。私はtarファイルを自動的に索引付けするxz圧縮にPIXZを使用します。圧縮する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を参照)、この問題を解決するためにハッキングを使用します。ファイルサイズが0のTarInfoを挿入し、ファイルの内容を保存し、最後に元のTarInfoのオフセットを見つけて正しいサイズで上書きします。 .... . しかし、読んでください。


「.tar.xzファイルからメタデータファイルをすばやく抽出できるようにtarballをインデックス化できるようにしたい」と述べたので、ZIPファイルのように見えます! ZIP形式は、まずすべてのファイルの内容を保存し、次にZIPの末尾にファイル情報とオフセットテーブルを保存します。そういう意味で言われたように、インデックスが作成されます。このツールはファイルの終わりから始めてファイルテーブルを簡単に見つけることができるため、ZIPの内容をすばやく一覧表示できます。

ZIPのデフォルト圧縮形式を使用するか、ZIPの保存モード(非圧縮)を使用して、そこにxyz.pcap.xzファイルを追加できます。 *.xz ファイルを ZIP に追加すると、Parallelxz などの外部コンプレッサーを簡単に使用できます。

Python 3zipfile.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を使用して、ピクルスメタデータをZIPファイルのエントリに直接シリアル化することもできます!)

zipfileのデフォルト圧縮を使用するには、ZipFileのデフォルト圧縮を設定できます。

with zipfile.ZipFile('mydata.zip', 'w', zipfile.ZIP_LZMA) as zf:

(デフォルトはZIP_STOREDです。これは圧縮がないことを意味し、xz圧縮データをそこに送信する場合はおそらく望むものです)。

よりzipファイルのドキュメント詳細については。最新のPythonにはより多くの機能があります。たとえば、Python 3.5では、実際にはzipファイルをパイプに書き込んでSSH経由でリモートホストに直接アップロードできます。


これがあなたに役立つことを願っています!本当にタールボールが必要な場合は試してみてください。この回答しかし、Python 3のzipfileソリューションを使用することが説明されているユースケースへのより良いアプローチだと思います!したがって、この形式が機能する場合は本当にお勧めします。

関連情報