web-dev-qa-db-ja.com

ファイルをアーカイブに保存するための仮想書き込み専用ファイルシステム

ほぼ(完全ではないが)大量の同一ファイルを作成する驚異的並列プロセスがあります。データが必要以上のスペースを消費しないように、ファイルを「オンザフライ」でアーカイブする方法はありますか?

プロセス自体がコマンドラインパラメータを受け入れ、作成された各ファイルの名前をstdoutに出力します。私はそれをparallel --gnuで呼び出しています。これは、入力(別のプロセスからのもの)の配布と出力の収集を処理します。

arg_generating_process | parallel --gnu my_process | magic_otf_compressor

簡単な例bashのパイプの最初の部分:

for ((f = 0; $f < 100000; f++)); do touch $f; echo $f; done

magic_otf_compressorはどのように見えるでしょうか?各入力行をファイル名として扱い、各ファイルを圧縮された.tarアーカイブ(処理されたすべてのファイルで同じアーカイブ!)にコピーしてから削除することになっています。 (実際には、処理された各ファイルの名前を出力するだけで十分です。別の| parallel --gnu rmがファイルの削除を処理できます。)

そのようなツールはありますか?各ファイルを個別に圧縮することは考えていません。これは、非常に多くのスペースを浪費することになります。 archivemount(ファイルシステムをメモリに保持します->不可能、ファイルが大きすぎて多すぎます)とavfs(Fuseと一緒に動作させることができませんでした)を調べました。私は何を逃しましたか?

私はそのようなツールを自分でハッキングすることからほんの一歩ですが、誰かが以前にそれをしたに違いありません...

[〜#〜] edit [〜#〜]:基本的に私はlibtarのstdinフロントエンドを探していると思います(コマンドラインフロントエンドではありません) tarは、コマンドラインから引数を読み取ります)。

8
krlmlr

tarはすべてのファイル名を事前に知りたいようです。そのため、オンザフライではなく、アフターザフライになります。 cpioにはその問題はないようです:

| cpio -vo 2>&1 > >(gzip > /tmp/arc.cpio.gz) | parallel rm
1
Ole Tange

RTFM(すべて!)の典型的なケース。 GNU tar-Tオプションは、アーカイブするファイルを別のファイルから読み取ります(私の場合、/dev/stdin-も使用できます)。また、--remove-filesオプションもあります。 :

alias magic_otf_compressor='tar --create -T - --remove-files -O | pixz'

(圧縮には並列バージョンのxzを使用しますが、代わりに好みのコンプレッサーを使用できます)。として使用される:

arg_generating_process |
  parallel --gnu my_process |
  magic_otf_compressor > file.tar.xz

[〜#〜] edit [〜#〜]:Oleが指摘しているように、tarはファイルのリスト全体を次のように読み取っているようです。何らかの理由で-Tオプション。次のテストでこれを確認します。

for ((f = 0; $f < 1000; f++)); do
    touch $f; echo $f;
done | tar -c -f otf.tar -T - -v

すべてのファイルが一度に印刷される前に、システムに1秒の遅延があります。対照的に、tarコマンドがcatに置き換えられた場合、すべてのファイルは作成時に出力されます。 サポートリクエスト タールの人たちに提出しました。見てみましょう。

EDIT ^ 2:ソースからの最新のtarがこれを修正します。 Ubuntu 13.10にはまだ含まれていませんが、14.04に含まれている可能性があります。

7
krlmlr

どういうわけか、これは堅実なコンプレッサー(テープベースのアーカイバ+圧縮)にとっては良い仕事ではないようです。ファイルを次々に挿入することは、Zipまたはアーカイブ内のランダムなファイルアクセスと増分挿入を可能にする他の形式の仕事のように見えます。

ファイルが類似しているという事実は、どちらの場合もあまり役に立ちません。 Zipでは、ファイルは個別に圧縮され、ソリッドコンプレッサーでは、通常、圧縮が行われるウィンドウがあります。

ファイルがテキストベースの場合、単一の参照ファイルと比較して差分を保存できます。バイナリの場合、少し注意が必要ですが、実行できます。

正式な方法もあります(書き込み専用ではなく、適切なファイルシステム)。たとえば、ZFSおよびBTRFSファイルシステムは透過的な圧縮を提供します。これを使用することもできます http://developer.berlios.de/projects/fusecompress

1
orion

明白ではないように思われるかもしれませんが、squashfsはこれに最適であり、カーネルにも実装されていると思います。バージョン4.1以降、squashfsmksquashコマンドラインまたはシェルスクリプトを介してmksquashfsは、アーカイブの作成時にファイルを生成します。

パイプを処理できます-たとえば、別のプロセスのstdoutをにキャプチャできますマウント可能なスカッシュアーカイブ-fifos-それはかなりクールです。あなたの場合、プロセスの出力をパイプでつなぐスクリプトロジスティクスを実行できれば、プロセスを完全にラップできますmksquashfsにあり、1つのアーカイブになります。 readmeからの動作について少し説明しますが、 詳細はこちら

Mksquashfs 4.1では、「動的疑似ファイル」と変更操作のサポートが追加されています。動的疑似ファイルを使用すると、Mksquashfsの実行時にファイルを動的に作成できます。その内容は、コマンドまたはシェルスクリプトの一部を実行した結果です。 modifiy操作を使用すると、ソースファイルシステム内の既存のファイルのmode/uid/gidを変更できます。

動的ファイルの例の作成

Dmesgからの出力を含むファイル「dmesg」を作成します。

    dmesg f 444 root root dmesg

リリース名、日付、ビルドホスト、および増分バージョン番号を含むファイルRELEASEを作成します。増分バージョンはシェルスクリプトの実行の副作用であり、Mksquashfsが実行されるたびに、他のシェルスクリプトを必要とせずに新しいバージョン番号が使用されるようにします。

    RELEASE f 444 root root \
        if [ ! -e /tmp/ver ]; then \
        echo 0 > /tmp/ver; \
        fi; \
        ver=`cat /tmp/ver`; \
            ver=$((ver +1)); \
            echo $ver > /tmp/ver; \
            echo -n "release x.x"; \
            echo "-dev #"$ver `date` "Build Host" `hostname`

デバイス/ dev/sda1からファイル入力に10Kをコピーします。通常、デバイス、fifo、または名前付きソケットが指定されたMksquashfsは、その特別なファイルをSquashfsファイルシステム内に配置します。これにより、これらの特別なファイルからの入力をキャプチャしてSquashfsファイルシステムに配置できます。

        input f 444 root root dd if=/dev/sda1 bs=1024 count=10
0
mikeserv