mapfile
によって生成されたddrescue
があり、各行が次のようになっている418個の不良セクターがリストされています(マイナスは不良ブロックを示します)。
Position Size
0x1CC7C68000 0x00001000 -
バイト単位の位置をパーティションの相対セクター番号に変換することで、debugfs
を使用してiノード番号を照会し、壊れたファイルのパスを見つけることができます。これを手動で行うことは、ほぼ2000の不良ブロックでは実行できないため、これを自動化したいと思います。ファイルシステムで一連のコマンドを実行するためにdebugfs
をスクリプト化する方法はありますか?
壊れたセクターのファイル名を取得するために現在行っていることは次のとおりです。
ddrescue
mapfile
の位置は、ディスクの先頭を基準にしたバイト単位です。最初に、512で除算して位置をセクター番号に変換し、次にパーティションの開始セクター位置を減算します。
最初のセクターのパーティション:91914240不良ブロック位置:0x1CC7C68000 10進数:123610759168絶対セクター位置:123610759168/512 = 241427264パーティション上の相対ブロック位置:241427264-91914240 = 149513024
したがって、不良セクタは、パーティションの開始に対して149513024
にあり、debugfs
を使用して、iノードを見つけることができます。
$ debugfs
debugfs: open /dev/sdd3
debugfs: icheck 149513024
Block Inode number
149513024 1183169
debugfs: ncheck 1183169
Inode Pathname
1183169 /username/foo/bar/baz
このプロセスを自動化して、ブロック位置のリストをdebugfs
に渡し、これらのブロックをiノードに解決し、iノードをフィルタリングしてマップされていないiノードを除外してから、ncheck
を使用してパスを解決できるようにします。残りのiノードの名前。これはdebugfsといくつかのシェルスクリプトで可能ですか?
私のrpi3b + SDカードが死んだ後、私は今日これをしなければなりませんでした。ファイルパスを自動的に吐き出すことを除いて、上記のbashスクリプトで行ったことを実行するpythonスクリプトを作成することになりました。ここで確認できます: https:/ /github.com/zkrx/rescue2path
このソリューションでは、まだスクレイピングされていないデータのチャンク( '/')もチェックします。ここではスクレイピングに非常に長い時間がかかり、完了する前に停止しました。
Arch wikiのこのエントリは特に役に立ちました: https://wiki.archlinux.org/index.php/Identify_damaged_files
私は自分の問題の解決策を見つけたと信じています。しかし、誰かがもっとエレガントな解決策を思いついたり、私の解決策に間違いを見つけたりできるかどうか、私はまだ興味があります。
結局のところ、debugfs
のstdinに書き込むことができたので、debugfs
の出力を分析するために、ddrescue
の一連のコマンドを生成するだけで済みました。
次のbashスクリプトは、ddrescue
によって作成された現在のディレクトリに_mapfile.ddrescue
_という名前のファイルが存在することを前提としています。
_for line in \
$(cat mapfile.ddrescue | \
grep -e "-$" | \
awk -F" " '{print $1}' | \
awk -F"0x" '{print $2}'); \
do \
position=$(( 16#$line / 512 - 91914240 )); \
result="$result $position"; \
done; \
echo -e "open /dev/sdd3\nicheck $result\nquit\n" | Sudo debugfs
_
このスクリプトの機能は次のとおりです。
mapfile
からddrescue
を解析します。これを_mapfile.ddrescue
_と名付けました。Ox
プレフィックスを削除します。$(...)
によって返されます。呼び出し手は、forループへの入力として機能するため、行には常に1つの位置が含まれます。$(( ... ))
式を使用して、位置の計算を行い、位置を512で除算し(たとえば、セクターあたりのバイト数)、パーティションの開始を減算します。私の場合は_91914240
_です。これにより、パーティションの開始を基準にしたセクター内の位置がわかります。$result
_に格納されているスペースで区切られたリストに連結します。debugfs
コマンドのstdinにパイプする改行区切りのコマンドリストを生成します。このコマンドはデバイスを開きます(私の場合は_/dev/sdd3
_)。次に、_$result
_でicheck
を実行し、debugfs
を終了します。このスクリプトを実行したとき、debugfs
はそれらのブロックのすべてのinodes
を見つけるのに長い時間がかかりました。私の場合、出力が出力されるまで数分間ハングしたように見えました。
スクリプトが完了したら、結果をテキストファイルにコピーして分析しました。幸いなことに、ほとんどのセクターは未割り当てのブロックを指しており、残りのセクターは同じ少数のinode
番号を指しています。 _<block not found>
_で行を削除し、重複を削除した後、残ったinodes
は4つだけで、debugfs
を使用してncheck
で手動で確認できました。これにより、4つのファイルパスが得られました。これらは、バックアップから復元しようとするファイルです。
背景私はもともとdd
から始め、256GBSSDの内容をより大きなSSDにコピーしたいと考えていました。 dd
は最後のパーティションの約45/185GBでI/Oエラーで中止されました。ただし、ddrescue
を使用すると、ドライブの99.99%を節約できます。最後に、上記の解決策で、残りの1700kbまたは418の不良領域がどのファイルに属しているかを確認し、壊れているファイルは4つだけでした。これにより、どのファイルが壊れているかがわかり、古いバックアップからそれらを復元できるため、復元されたデータに対する信頼が十分に高まりました。