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


8

非常に多くの(完全ではないが)同一のファイルを大量に作成する、恥ずかしいほど並列処理を行っています。「オンザフライ」でファイルをアーカイブして、データが必要以上のスペースを消費しないようにする方法はありますか?

プロセス自体はコマンドラインパラメータを受け入れ、作成された各ファイルの名前を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と連携させることができませんでした)。私は何を逃したのですか?

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

編集:本質的に私は標準入力フロントエンドを探していると思いますlibtartarコマンドラインから引数を読み取るコマンドラインフロントエンドとは対照的です)。


ネイティブ圧縮のフォーマットでファイルを書き込むことを検討しましたか?たとえば、hdf5は、gzipまたはszip圧縮で記述されているため、圧縮できます。Hdf5はMPIもサポートしているので、これらの厄介な並列問題でもうまく機能します。
ケーシー2014年

2
圧縮と重複排除が必要な場合は、zfsが思い浮かびます。
ステファンChazelas

@casey:HTMLですが、HDF5コンテナを使用できると思います。これはまだ検討していません。
krlmlr 2014年

@StephaneChazelas:これはユーザーランドで実装できますか?
krlmlr 2014年

回答:


1

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

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

ありがとう。したがって、RTFMでも十分ではありません;-) tar処理する次のファイル名を返す関数があることを確認するためにのコードを調べただけで、もう一度ドキュメントを読みました。-そのため、stdout対象とするgzipプロセス置換を介してプロセスとstderrにリダイレクトされるstdoutパイプの次のステップで処理されましたか?
krlmlr 2014年

うん。>>()構文はすべてのシェルで機能するわけではありませんが、Bashでは機能します。
Ole

tar質問に追加した簡単な例を使用して、最初にファイルリストを読み取ることを確認できます。ただし、tarのソースコードをもう一度読むと、インクリメンタルアーカイブを作成していない場合は、「オンザフライ」でファイルのリストを読み取る必要があるようです。残念ながら、tarソースからコンパイルするとエラーが発生します... :-(
krlmlr '12

私は、出力の最後の行抑制するための方法発見していないcpio以外は、grep -v 'blocks$'。(head -n -1非常に大きなバッファーを使用します...)このソリューションを少しハックしますが、気にしないでください;-)
krlmlr

奇妙な@krlmlr:head -n -1数GBのデータで実行した場合、16 MB しか使用しません。いつでもperlを使用できます:perl -ne 'print $ last; $ last = $ _'
Ole

7

古典的なケースRTFM(それのすべて!) -TGNU のオプションは、tarアーカイブするファイルを別のファイルから読み取ります(私の場合は/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

編集: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 ^ 2tarソースからの最新のものはこれを修正します。Ubuntu 13.10にはまだ含まれていませんが、14.04に含まれている可能性があります。


1

どういうわけか、これはソリッドコンプレッサー(テープベースのアーカイバー+圧縮)には適していません。ファイルを次々と挿入するzipことは、アーカイブ内のランダムなファイルアクセスと増分挿入を可能にするためのジョブまたは他の形式のように見えます。

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

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

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


私のファイルはそれぞれ約100kです。たとえば、コンプレッサーが1Mのウィンドウを使用するのに十分ではないでしょうか?xzデフォルトのディクショナリサイズである8M(デフォルトの圧縮レベル-6)で動作しているようですが、これは私のユースケースでは十分なようです。-参照ファイルとの差分は便利ですが、最初に参照ファイルを作成する必要があります。圧縮ファイルシステムは、内容がほぼ同一のファイルを検出しますか?
krlmlr 2014年

ファイルシステムを圧縮しても、ファイル全体は圧縮されません(zipも圧縮されません)。ただし、btrfsコピーオンライト機能があるため、ファイルをコピーしてその一部を変更しても、変更した部分のみが保存されます。この方法でファイルを作成しない場合、重複排除ツールが存在すると思われますが、btrfsまだ成熟した安定したファイルシステムではなく、これは開発の初期段階にあります。しかし、今、私はそれについて考えています。lessfs.com/ wordpress
orion

私のユースケースではソリッドコンプレッサーを使用して印象的な圧縮率を実現していますが、概要を説明したように、ファイルがディクショナリサイズよりも大きい場合は結果が悪化すると思います。
krlmlr 2014年

0

それは明白に見えないかもしれませんが、私squashfsはこれには完璧だろうと思います-そしてそれはカーネルで実装さえされています。バージョン4.1以降は、コマンドラインまたはシェルスクリプトを介して指定された疑似ファイルsquashfs処理でき、アーカイブを作成するときにファイルを生成します。mksquashmksquashfs

パイプを処理できます。たとえば、別のプロセスをstdoutマウント可能なスカッシュアーカイブに取り込むことができます。fifosを含めても、非常に優れています。あなたのケースでは、プロセスの出力をパイプライン処理するスクリプトロジスティクスを理解できれば、プロセスを完全ラップmksquashfsして、単一のアーカイブで仕上げることができます。ここでは、readmeそれがどのように機能するかについて少し説明します

Mksquashfs 4.1は、「動的疑似ファイル」のサポートと変更操作を追加します。動的な疑似ファイルを使用すると、Mksquashfsの実行時にファイルを動的に作成できます。その内容は、コマンドまたはシェルスクリプトの実行結果です。変更操作により、ソースファイルシステム内の既存のファイルのモード/ 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

私が概説したインフラストラクチャ内でこれはどのように機能しますか?
krlmlr 2014年

ファイル名をmksquashの呼び出しスクリプトに書き込むようにプロセスを取得し、実行時にそれらを追加し続ける必要があります。または、実行時にスカッシュが読み取って圧縮するtmpfsにさえも入ります。または、別の方法で述べたように、別の方法で-上記のddの例と同じようにcpioを呼び出しますが、cpioではそのコピー機能を使用します。いずれにせよ-それは間違いなくその場で読み取り、作成、圧縮します。
mikeserv 2014年

ファイル間で圧縮されますか?
krlmlr 2014年

入力をストリームに圧縮します-すべてのiノード、すべて。私はそれをddで使用しましたが、それはかなりクールでした-私は常に1MBのブロックサイズとxz圧縮を使用しています。
mikeserv 2014年

これはオプションのように見えますが、あなたの答えから、たとえば、ディレクトリtestfileこのディレクトリ内のファイルでsquashfsアーカイブを作成する方法はわかりません。簡単な例を教えていただけますか?
krlmlr 2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.