SHA1合計(ハッシュが一致する場合にファイルが一致すること、およびファイルが一致しない場合にハッシュが一致しないことを数学的に非常に確実に保証)を追加すると、データ整合性の尺度が追加され、ディスクサブシステムが書き込み中に(サイレント)ミスをした可能性があります。サイレント破損はまれですが、発生した場合は陰湿です。
もちろん、読み取り中にランダムなエラーが発生した場合、結果が混乱する可能性がありますが、その場合、合計は非常に高い確実性でとにかく一致しません。言い換えれば、システムが破損している場合(RAMまたはディスクが間違ったビット/反転ビット/破損したデータを生成している場合)、シンプル&&
が成功する可能性がある場所でこれは失敗し、破損したデータでこのrm
行に到達する可能性はゼロになります小さい(ほとんどのエラーはランダムな方法でデータを破損する傾向があるため、リードバック中にランダムな変更がSHA1でハッシュ衝突を引き起こす可能性は驚くほど小さいです。)
#!/bin/bash
set -e
set -o pipefail
ORIGSUM=$(gzip -dc file.gz | tee >(xz > file.xz) | sha1sum)
NEWSUM=$(unxz -c file.xz | sha1sum)
if [ "${ORIGSUM}" = "${NEWSUM}" ]; then rm file.gz; fi
set -e
同じようにすぐにシェルスクリプト出口を作る任意のスクリプトの行は0以外の終了コードを返します。
その後、我々は、使用tee
するファイルの非gzip圧縮された出力をコピーするコマンドを両方xz
の圧縮機、およびへのsha1sum
プログラム。sha1sum
g1アーカイブに含まれる元のデータのSHA1合計を、sha1sumプログラムに一時的に解凍することにより計算します。sha1sumプログラムはデータを読み取り、合計を計算してからデータを破棄します。を使用することによりtee
、ファイルを解凍するCPUコストを1回支払うだけで済みます。
次に、追加の計算コストの高いステップを実行して(超追加検証用)、ファイルのxz圧縮を(一時的にストリームに)ストリップし、sha1sumにパイプして、「新しいファイル」SHA1合計を取得します。
次に、2つの合計を比較し、それらが等しい文字列ではない場合、またはそれらのいずれかまたは両方が長さゼロの場合、スクリプトエラー(これはのおかげで終了します)を取得するset -e
か、ファイルが削除されました。else
必要に応じて、ユーザーフレンドリーなエラー処理の句を実装できますが、この重要なスクリプトは、コマンドをインタラクティブに実行するユーザーにとってあまり有益ではありませんが、非常に安全です。
最後に、file.gz
唯一のリンク解除される場合に限り、非圧縮の内容file.gz
とは、file.xz
ハッシュが何か悪いのオッズは何だろう間違っている(確実性の天文学的に高い程度で、計算された時点で正確に同一であり、 1に1のように、その後に300個のゼロがある)その時点で、このスクリプトの終了後にデータが破損することを心配するだけです。;)
性能
このスクリプトは、実行する部分を除き、問題の元のスクリプトとほぼ同じ速度で実行されますunxz
。幸いなことに、LZMAからの圧縮解除は非常に高速で、通常のZipとほぼ同じ速度で、LZMA への圧縮よりも1桁高速です。あなたは高速CPUを持っており、ファイルが十分に小さい場合には、これは追加しないでくださいあまりにもスクリプトに多くのランタイムをしていますが、パフォーマンス上のデータの整合性を重視すれば、それは明確な勝利です。
クレジットが支払われる場合のクレジット
StackOverflowに関するこの回答は、このスクリプトの作成に大いに役立ちました。
&&
ない||
でくださいと思います&& rm file.gz
。それ以外の場合は||
、失敗しfile.gz
たxz
場合でも削除されます。これは望ましくありません。