LinuxのHDDの自己診断でエラーの場合に壊れたファイルを特定する手順の説明です。
今回の実例では、HDDのSMART情報を確認した際に、Current_Pending_Sector の値が1になっていて、不良セクタが存在していました。
そこでHDDの自己診断を行うとエラーが見つかり、壊れたファイルを特定しました。
ディスクのSMART情報確認と自己診断
まず、Linux での HDDのSMART情報の確認方法です。
次の記事の「SMART情報表示」までの手順でディスクのSMART情報を確認します。
Linuxでの HDDの S.M.A.R.T.情報の取得と、HDD自己診断の実施方法
・物理HDDの確認
・HDDが SMART対応か確認
・SMART情報表示
以下の説明では、HDDのデバイス名は /dev/sda とします。
SMART情報を確認してみると、Current_Pending_Sector の値が1になっていました。
# smartctl /dev/sda -A
=== START OF READ SMART DATA SECTION ===
SMART Attributes Data Structure revision number: 16
Vendor Specific SMART Attributes with Thresholds:
ID# ATTRIBUTE_NAME FLAG VALUE WORST THRESH TYPE UPDATED WHEN_FAILED RAW_VALUE
1 Raw_Read_Error_Rate 0x002f 200 200 051 Pre-fail Always - 139
3 Spin_Up_Time 0x0027 139 138 021 Pre-fail Always - 4041
4 Start_Stop_Count 0x0032 100 100 000 Old_age Always - 57
5 Reallocated_Sector_Ct 0x0033 200 200 140 Pre-fail Always - 0
7 Seek_Error_Rate 0x002e 200 200 000 Old_age Always - 0
9 Power_On_Hours 0x0032 086 086 000 Old_age Always - 10588
10 Spin_Retry_Count 0x0032 100 253 000 Old_age Always - 0
11 Calibration_Retry_Count 0x0032 100 253 000 Old_age Always - 0
12 Power_Cycle_Count 0x0032 100 100 000 Old_age Always - 55
192 Power-Off_Retract_Count 0x0032 200 200 000 Old_age Always - 30
193 Load_Cycle_Count 0x0032 200 200 000 Old_age Always - 26
194 Temperature_Celsius 0x0022 107 099 000 Old_age Always - 36
196 Reallocated_Event_Count 0x0032 200 200 000 Old_age Always - 0
197 Current_Pending_Sector 0x0032 200 200 000 Old_age Always - 1
198 Offline_Uncorrectable 0x0030 100 253 000 Old_age Offline - 0
199 UDMA_CRC_Error_Count 0x0032 200 200 000 Old_age Always - 0
200 Multi_Zone_Error_Rate 0x0008 100 253 000 Old_age Offline - 0
HDDの自己診断(short)を実行してみます。
自己診断について詳しくは、Linuxでの HDDの S.M.A.R.T.情報の取得と、HDD自己診断の実施方法 の「HDDの自己診断」を参照して下さい。
次のコマンドで自己診断(short)を実行します。
# smartctl -t short /dev/sda === START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION === Sending command: "Execute SMART Short self-test routine immediately in off-line mode". Drive command "Execute SMART Short self-test routine immediately in off-line mode" successful. Testing has begun. Please wait 2 minutes for test to complete. Test will complete after Sat Sep 17 12:40:10 2016 Use smartctl -X to abort test.
しばらくして、自己診断の結果を確認します。
# smartctl -l selftest /dev/sda
=== START OF READ SMART DATA SECTION ===
SMART Self-test log structure revision number 1
Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error
# 1 Short offline <strong>Completed: read failure</strong> 90% 10590 267381314
Status が ‘Completed: read failure’ でエラーになっていました!!
LBA_of_first_error 列はエラーが起こった箇所を示します。
(正しくは、最初に読み込みエラーが起こったセクタ番号です)
今回の例では、LBA_of_first_error は 267381314 です。
さて、エラーによってディスクのどの inode が壊れているかどうかは、以降の手順で確認します。
更に以降の手順で、inode から壊れたファイル名を特定します。
エラー箇所(inode)の特定作業
LBA_of_first_error が示す箇所は、どの inode なのかを、以下の作業で特定します。
今回の例では、LBA_of_first_error は 267381314 で、これはエラーが起こったセクタ番号を示します。
このセクタがどのパーティション上にあるかを確認します。
まず、fdisk を下記のように実行します。
# fdisk -lu /dev/sda Disk /dev/sda: 500.0 GB, 500000514048 bytes 255 heads, 63 sectors/track, 60788 cylinders, total 976563504 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x0000f3ff Device Boot Start End Blocks Id System /dev/sda1 * 2048 973062143 486530048 83 Linux /dev/sda2 973064190 976562175 1748993 5 Extended /dev/sda5 973064192 976562175 1748992 82 Linux swap / Solaris
Start、End 列は各パーティションの開始セクタ、終了セクタです。
/dev/sda1 はセクタ 2048~973062143 で、LBA_of_first_error の 267381314 はこの範囲内です。
従って、エラーが起こったパーティションは /dev/sda1 だということが分かります。
このパーティションの開始セクタ(今回の例では 2048)をメモしておきます。
後ほど、この値を使用します。
ここで、該当パーティションの System 列が「Linux LVM」と表示された場合は、作業方法が異なります。
以下のサイトに詳しい手順が説明されていますので、そちらを参照して下さい。
ぱぱらくだ日記: Linux LVMでのCurrent_Pending_Sectorの対処方法
ここでは、System列が「Linux」の場合の手順になります。
エラーが起こったセクタ(LBA_of_first_error)が、ファイルシステム上のどのブロック番号かを調べます。
該当パーティション(この例では /dev/sda1)のブロックサイズを調べます。
# tune2fs -l /dev/sda1 | grep 'Block size:' Block size: 4096
ブロックサイズは 4096 でした。
ブロック番号を次の式で計算します。
計算結果の小数点以下は切り捨てます。
ブロック番号=(L-S)*512/B L:LBA_of_first_error の値(今回の例では 267381314 ) S:エラーが起こったパーティションの開始セクタ番号(今回の例では 2048) B:ブロックサイズ(今回の例では 4096 )
ブロック番号は、(267381314-2048)*512/4096 = 33422408.25 となり、小数点以下切り捨てして 33422408 になります。
次に、ブロック番号から inode情報を調べます。
debugfs コマンドを実行します。実行後、「debugfs:」と出て入力待ちになります。
# debugfs debugfs 1.41.12 (17-May-2010) debugfs:
「open /dev/sda1」と入力します。
しばらく経つと、再度 debugfs: と表示されて入力待ちになります。
「icheck ブロック番号」と入力します。
今回の例では、「icheck 33422408」と入力します。
しばらく待つと、該当ブロック上の inode番号が表示されます。
Block Inode number 33422408 <block not found>
この例では
該当箇所は未使用です。幸運にもファイルは配置されていません。
debugfs: で quit と入力して debugfs を終了し、早急に必要なファイルをバックアップしましょう。
“Inode number” で数値が表示されたら、それは inode番号です。
該当箇所にファイルが配置されており、残念ながら、そのファイルは壊れています。
Block Inode number 33422408 8241259
以降の手順では、どのファイルが壊れているかを特定します。
壊れたファイルを特定する
debugfs コマンドの続きです。
debugfs: と表示されて入力待ちになっている状態で、「ncheck inode番号」と入力します。
今回の例では、「icheck 8241259」と入力します。
しばらくすると、結果が出ます。
Inode Pathname 8241259 /var/lib/mysql/ibdata1
指定したinodeに対応するファイルが表示されます。
この例では、/var/lib/mysql/ibdata1 です。
これ、MySQL のデータベースファイルでした!!!!ショックです。
debugfs: で quit と入力して、debugfsの終了です。
さて、壊れていたファイルですが、復旧はあきらめなくてはなりません。
コピーでバックアップも出来ません。次のようにエラーになります。
# cp -a /var/lib/mysql/ibdata1 /tmp/ibdata1 cp: reading `/var/lib/mysql/ibdata1': 入力/出力エラーです
MySQL のデータベースファイルなので、mysqldump でバックアップとろうとしても、これも失敗します。
mysqldump: Error 2013: Lost connection to MySQL server during query when dumping table `data` at row: 16278730
今回の例では、この後、HDDは壊れて起動できなくなりました。
皆さんも同様の状態になったら、早急にその他必要なファイルをバックアップしましょう。
参考
大徳日記 » 不良セクタの直し方
Digital SeeTake: HDDの異常を検知する「SMART」と不良セクタの修復
Bad block HOWTO for smartmontools (現在存在しないので、 InternetArchives上のリンクを記載しています)
ぱぱらくだ日記: Linux LVMでのCurrent_Pending_Sectorの対処方法
コメント