最近、2.5TBの障害のあるディスクを部分的に回復しました。 ddrescue
は、ループバックモードでマウントできるイメージを作成しました。2.1TBが回復し、450GBが欠落していますが、残念ながらディスク全体に広がっています。
影響を受けるファイルを確認するには、filefrag -v
を使用して、ddrescue
によって生成されたマップファイルを確認します。
しかし、それには時間がかかります。回復しているのはビデオファイルのみであるため、ゼロの大きなストレッチは予想されませんが、ddrescue
がディスクからデータを読み取らなかった場所に存在することがわかりました。
したがって、ファイルにすべてゼロの(任意の)大きなパッチがある場合は、ファイルをスキャンするコマンドが必要になります。実際には、これらは常に512バイトの倍数であり、常に512バイトのアドレスで始まります。そのようなバイナリバイトシーケンス(つまり、512× '\ 0')についてファイルをスキャンできるコマンドはありますか?
別のアプローチ、したがって私からの別の答え。
ddrescue
自体を使用して、ゼロを検索できます。 --generate-mode
を使用します。
ddrescue
が--generate-mode
オプションで呼び出されると、デフォルトの「レスキューモード」とは異なる「生成モード」で動作します。つまり、--generate-mode
オプションを使用した場合、ddrescue
は何もレスキューしません。後で使用するためにmapfile
を生成しようとするだけです。[…]
ddrescue
は、場合によっては、mapfile
とinfile
の(部分的な)コピーからおおよそのoutfile
を生成できます。これは、正確なmapfile
とほぼ同じです。これは、すべてゼロを含むセクターがレスキューされなかったと単純に想定することで実現されます。[…]
ddrescue --generate-mode infile outfile mapfile
( ソース )
ファイルが前回のoutfile
実行からのddrescue
であると仮定しましょう。 infile
として使用することはできません(ddrescue
とinfile
が同じファイルの場合、outfile
は機能しないため)、ダミーのファイルが必要です。/dev/zero
で十分です。すべてのゼロを見つけるには、-b 1
が必要です。これはコマンドです(mapfile
は存在してはなりません):
ddrescue -b 1 --generate-mode /dev/zero file mapfile
mapfile
内のデータブロックのリストに?
が含まれるすべてのエントリは、ゼロのブロックを意味します(-b 1
の場合、1つのゼロもブロックです)。 ddrescue
のマップファイル構造 を参照してください。その後、mapfile
から情報を取得できます。
たとえば、次のコマンドは、ゼロの最大ブロックの長さ(16進数、-b 1
のためにバイト単位)を示します(空の出力は、何もなかったことを意味します)。
grep '0x.*0x.*[?]' mapfile | awk -F ' ' '{print $2}' | sort -ru | head -n 1
速度を上げるには、より大きなブロックサイズ(-b
)を使用することをお勧めしますが、あるブロック内で始まり、次のブロック内で終わるゼロのブロックは、選択したブロックサイズよりわずかに長くても、気付かない場合があります。それらのオフセットが重要になります。
長さがN
バイト以上のゼロのストレッチを見逃さないようにするには、最大M=$(((N+1)/2))
バイトのブロックサイズが必要です(たとえば、5
の場合は最大N=10
、6
の場合はN=11
)。コマンド
ddrescue -b "$M" --generate-mode /dev/zero file mapfile
データブロックのリストに?
が含まれるすべての行が少なくともM
ゼロ(右側のオフセット)を意味するマップファイルを生成しますが、N
ゼロのすべてのストレッチ(オフセットに関係なく)は確実にそのような行を生成します。 M
の2つのブロックは少なくともN
であるため、次の理由が当てはまります。
データブロックのリストから?
の行を取得し、
mapfile
の2番目の列、単位はM
であることを忘れないでください)が0x2
以上の場合、この位置にはN
以上のゼロがあります。0x1
の場合、この位置の周囲に少なくともN
ゼロがあるかどうかをさらに調査する必要があります。N
ゼロのストレッチはありません。実際には、これらは常に512バイトの倍数であり、常に512バイトのアドレスで始まります。
この場合
ddrescue -b 512 --generate-mode /dev/zero file mapfile
それらすべてを見つけてマッピングします。
grep
にnull文字を明示的に検索させると、私にはわかりません。ただし、512個の連続する同一の文字(ほとんどありそうもない)を検索するようにするのは、いくぶん簡単です。
grep -Eal '(.)\1{511}' the_files
512個の同一文字のシーケンスが見つかったファイルをリストします。 -a
パラメーターは、ヌル文字と一致させるために必要です(そうでない場合、行末文字と見なされ、無視されます)。
xenoidの答え 影響を受けるファイルをすばやく見つけることができます。さらに確認して分析するには、次のコマンドを実行します。
<"file" tr '\000-\377' 'oL' | fold -w 512 | grep -vn 'L' | cut -f 1 -d ':'
これは次のように機能します。
"file"
が開かれ、最初のコマンドにストリーミングされます。tr
はすべてのヌル文字をo
に変換し、すべての非ヌル文字はL
に変換します。fold
は、512文字ごとに改行を挿入します。現時点では、ストリームは純粋なテキストとして扱うことができます。grep
は、L
を含まない行を取り、それらの番号を出力します。cut
はこれらの番号を分離します(ooo…
を削除します)。このようにして、ゼロで満たされた512バイトのチャンクの序数を取得します。番号付けは1
で始まります。出力をwc -l
に渡して、特定のファイルで影響を受けるチャンクの数を確認します。
これは時々欲しかったものなので、興味をそそられました。少し検索して、 this Python 3 program 。
ページの下部でwget
コマンドを実行しましたが、完全に機能します(ただし、権限によってはSudo
が必要になる場合があります)。 grep
と同様に、正規表現検索を含む多くの強力なオプションがあります。ヘッダーの例はそれらのいくつかを示しています。 bgrep --help
は完全なリストを提供します。
使用するには、512個のダブルゼロを含む実行文字列が必要になります。入力せずに、次のようなものを使用してください。
bgrep -l $(for f in {0..511}; do echo -n 00; done) files...
-r
オプションを使用して、完全なディレクトリツリーをトラバースすることをお勧めします。
私はこの答えを追加しました。他の人が不十分であるためではなく(Kamil Maciorowskiのコマンドシーケンスの創意工夫が特に好きでした)、この質問に遭遇する関連する問題を持つ他の人(私のような)にとって価値があるかもしれないからです。