ほぼ(完全ではないが)大量の同一ファイルを作成する驚異的並列プロセスがあります。データが必要以上のスペースを消費しないように、ファイルを「オンザフライ」でアーカイブする方法はありますか?
プロセス自体がコマンドラインパラメータを受け入れ、作成された各ファイルの名前を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
は、コマンドラインから引数を読み取ります)。
tar
はすべてのファイル名を事前に知りたいようです。そのため、オンザフライではなく、アフターザフライになります。 cpio
にはその問題はないようです:
| cpio -vo 2>&1 > >(gzip > /tmp/arc.cpio.gz) | parallel rm
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に含まれている可能性があります。
どういうわけか、これは堅実なコンプレッサー(テープベースのアーカイバ+圧縮)にとっては良い仕事ではないようです。ファイルを次々に挿入することは、Zip
またはアーカイブ内のランダムなファイルアクセスと増分挿入を可能にする他の形式の仕事のように見えます。
ファイルが類似しているという事実は、どちらの場合もあまり役に立ちません。 Zip
では、ファイルは個別に圧縮され、ソリッドコンプレッサーでは、通常、圧縮が行われるウィンドウがあります。
ファイルがテキストベースの場合、単一の参照ファイルと比較して差分を保存できます。バイナリの場合、少し注意が必要ですが、実行できます。
正式な方法もあります(書き込み専用ではなく、適切なファイルシステム)。たとえば、ZFSおよびBTRFSファイルシステムは透過的な圧縮を提供します。これを使用することもできます http://developer.berlios.de/projects/fusecompress
明白ではないように思われるかもしれませんが、squashfs
はこれに最適であり、カーネルにも実装されていると思います。バージョン4.1以降、squashfs
はmksquash
コマンドラインまたはシェルスクリプトを介して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