パイプの出力をコピーできますか?

パイプの出力をコピーできますか?

作業は簡単です。私のスクリプトの一部はmd5とsha1ハッシュを計算する必要があります。入力はファイル(大きなファイル)で、後で出力の組み合わせのためにハッシュをMD変数とSH変数に入れる必要があります。

処理されるファイルは非常に大きいが(数百GB)、何度も読み書きするデータの種類を使用しようとしています。私はプロセス置換であることを発見し、次のように採用しました。

$ dd if=big.tgz 2>/dev/null |tee >(sha1sum ) > >(md5sum ) ;

変える:

$ SH=$(sha1sum big.tgz); MD=$(md5sum big.tgz);

しかし、私は以下を見つけました。

  • どちらもおおよその時間を必要とするため、リソースと時間を節約できません。 40秒(4.776GBファイルの場合)

  • >(md5sum )後でスクリプトで使用するために子プロセスの結果を変数MDに保存する方法がわかりません。

私はPipelineexecを理解しようとしていますが、素敵でカラフルなイラストがあっても成功しませんでした。

VAR = $(command)に加えて、出力を変数にリダイレクトする他の方法はありますか?

答え1

パフォーマンスの面では、CPUによって制限されることがあります。実際、MD5とsha1sumは40秒で4.7TBを送信して素早く感じられます。だからこうして仕事をしても。ディスクIOが少なくなることは言及する価値があります。

実際にはこれを行う必要はありませんdd。後で使用するために、sha1sumとmd5sumの出力をファイルに直接書き込むこともできます。

tee < big.tgz  >(sha1sum > big.tgz.sha1 ) > >(md5sum > big.tgz.md5 )
sha1=`cat big.tgz.sha1`
md5=`cat big.tgz.md5`

私が知っている1つの2つの変数を同時に異なる値に設定する方法がないので、このような一時ファイル(big.tgz.sha1および)を使用することをお勧めします。big.tgz.md5どちらも変数に直接キャプチャできますが、どちらもキャプチャすることはできません。同じ標準出力を許可してmd5sum同時に記録すると、予測できない問題が発生する可能性があります。sha1sum

答え2

さて、内部に別のリダイレクトを追加できます。

tee < big.tgz >(sha1sum > big.tgz.sha1sum) >(md5sum > big.tgz.md5sum)

sha1とmd5を簡単に区別できるので、出力をそのまま得ることもできます(長さが違うのでどちらがどれか混同する必要はありません)。

を使用せずに独自に複数のチェックサムを計算できるユーティリティもありますtee

実際、上記の内容は作成する必要はありませんtee

sha1sum big.tgz > big.tgz.sha1sum &
md5sum big.tgz > big.tgz.md5sum
wait # for sha1sum

理論的には、これはディスクからデータを2回読み取るので良いことではありません。

実際に2つのリーダーを並列に(およびバックグラウンドで)実行すると、ディスクキャッシュはそれを処理し、データが実際に一度だけ読み取られるようにする必要があります。これは、ハッシングが高速でI/Oが遅いため、どのプロセスも他のプロセスから離れることができないと仮定します。

(私は以前に別の文脈で2回読むことについて投稿しました。md5sumでpvを使う- 一般的に効果がありますが、わずかなリスクがあるため、teeまだより安定した方法です。 )

答え3

parsetGNU Parallel は変数を並列に設定し、--tee複数のコマンドに入力を送信するために使用されます。

parset md5,sha1,sha256 --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo $sha1

parset sumarr --pipe --tee {} ::: md5sum sha1sum sha256sum < bigfile
echo ${sumarr[1]}

関連情報