刹那(せつな)の瞬き

Willkömmen! Ich heiße Setsuna. Haben Sie etwas Zeit für mich?

Ubuntuで壊れかけのディスクを小容量のディスクにクローンして復旧を試みた

以前に不具合が発生して復旧した HDD ですが、最近は稀にデバイスそのものを認識しなくなるので、色々と心配になってきました。

相変わらず HDD に fsck や badblocks を試してみても不良ブロックは見つからないし、smartctl で自己診断してログを調べても異常は見当たりません。
シーク音も正常っぽいし、電源供給も安定してるし、未だに原因が特定できません。

しかし、これ以上つまらない事で悩みたくないので、この HDD が壊れてしまう前に別のディスクにクローンする事にしました。

苦労はしましたが、最終的にはクローンに成功したので、以下はその備忘録です。
※操作に失敗するとデータ消失の危険があります。要注意です。

1. クローン作成

まず PC の SSD/HDD 構成は次のとおりです。

バイス OS 用途
/dev/sda (SSD) Windows10 ※今回は未使用
/dev/sdb (SSD) Ubuntu 20.04 今回の復旧作業で使用する OS
/dev/sdc (HDD) Ubuntu 18.04 元のディスク
/dev/sdd (HDD) 未割り当て 復旧用ディスク

今回は GUID もデータも「元のディスク」の内容を丸ごと「復旧用ディスク」にクローンするので、さらに別のディスクに存在する Ubuntu 20.04 で作業します。

ここで、/dev/sdd に接続した「復旧用ディスク」は、本来は複製元より容量が大きいディスクが望ましいのですが、あいにく手元には古く容量が小さい HDD しかありませんでした。

(1) ディスクの認識状態を確認

Ubuntu 20.04 (/dev/sdb) の起動後、fdisk を実行して各ディスクの状態を確認します。

$ sudo fdisk -l

〜(ざっくり省略)〜
ディスク /dev/sdc: 465.78 GiB, 500107862016 バイト, 976773168 セクタ
Disk model: WDC WD5000LPVX-0
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 4096 バイト
I/O サイズ (最小 / 推奨): 4096 バイト / 4096 バイト
ディスクラベルのタイプ: gpt
ディスク識別子: 2D86DB2C-8285-4483-88D1-EDAF06E991C5

デバイス   開始位置  最後から    セクタ サイズ タイプ
/dev/sdc1      2048   1050623   1048576   512M EFI システム
/dev/sdc2   1050624 976773119 975722496 465.3G Linux ファイルシステム


ディスク /dev/sdd: 465.78 GiB, 500106780160 バイト, 976771055 セクタ
Disk model: WDC WD5000AAKS-0
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: gpt
ディスク識別子: C40395DA-2155-AB44-9638-EA20F1BE4C04

実行結果から「復旧用ディスク」のセクタ数が 2,113 セクタ少ない事が確認できます。

この時点で「元のディスク」の /dev/sdc2 を縮小しておくと、後述の作業が楽になるのですが、デバイスの認識具合が微妙なので、この HDD に対する余計な負荷は避けたいところ。
今回はそのまま現状維持で、敢えて茨の道を行きます。

(2) ディスクのクローン

末尾の 2,113 個のセクタが欠落しますが、強引にクローンしてみます。

いつもは dd で済ませてますが、今回は GNU ddrescue を使ってみました。

$ sudo apt install gddrescue 
$ sudo ddrescue -f -n -v /dev/sdc /dev/sdd dd.log

dd.log の内容によると、処理に 3 時間を要してますが、特にエラーはありません。
dd.log には欠落したセクタの位置とサイズも記録されていますが、今回はスルーします。

ちなみに、sudo dd if=/dev/sdc of=/dev/sdd bs=4M conv=sync,noerrorを実行すると、最後に書き込みエラーで「デバイスに空き領域がありません」と出ますがクローンは作成されます。※1.5時間くらいで終了しました。バッファ大事...

(3) 複製元ディスクを撤去

ここで、一旦 PC をシャットダウンして、電源 OFF にします。

同じ GUID を持つディスクが 2 つ存在すると色々面倒なので、混乱しないように複製元のディスクを PC から外します。

2. パーティション復旧作業

「元のディスク」を外したので、PC の SSD/HDD 構成は次のとおりです。

バイス OS 用途
/dev/sda (SSD) Windows10 ※今回は未使用
/dev/sdb (SSD) Ubuntu 20.04 今回の復旧作業で使用する OS
/dev/sdc (HDD) クローンした Ubuntu 18.04 復旧用ディスク

「元のディスク」の内容で丸々上書きした「復旧用ディスク」ですが、この時点では PC にデバイスとして認識されているものの、まだ OS 起動はできません。

再び作業用の OS を起動して「復旧用ディスク」をデバイス本来の情報に合わせて修復します。

(1) クローンした HDD の確認

Ubuntu 20.04 (/dev/sdb) を起動したら「復旧用ディスク」の状態を確認します。

sfdisk で調べると、セクタ数不整合のエラーが表示されます。

$ sudo sfdisk -l /dev/sdc
GPT PMBR size mismatch (976773167 != 976771054) will be corrected by write.
ディスク /dev/sdc: 465.78 GiB, 500106780160 バイト, 976771055 セクタ
Disk model: WDC WD5000AAKS-0
単位: セクタ (1 * 512 = 512 バイト)
セクタサイズ (論理 / 物理): 512 バイト / 512 バイト
I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト
ディスクラベルのタイプ: dos
ディスク識別子: 0x7bf55bc8

デバイス   起動 開始位置  最後から    セクタ サイズ Id タイプ
/dev/sdc1              1 976771054 976771054 465.8G ee GPT

パーティション情報がなくなってるようにも見えますが、gdisk で調べると、得られる情報が異なります。

$ sudo gdisk -l /dev/sdc
GPT fdisk (gdisk) version 1.0.5

Warning! Disk size is smaller than the main header indicates! Loading
secondary header from the last sector of the disk! You should use 'v' to
verify disk integrity, and perhaps options on the experts' menu to repair
the disk.
Caution: invalid backup GPT header, but valid main header; regenerating
backup header from main header.

Warning! One or more CRCs don't match. You should repair the disk!
Main header: OK
Backup header: ERROR
Main partition table: OK
Backup partition table: ERROR

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: damaged

****************************************************************************
Caution: Found protective or hybrid MBR and corrupt GPT. Using GPT, but disk
verification and recovery are STRONGLY recommended.
****************************************************************************
Disk /dev/sdc: 976771055 sectors, 465.8 GiB
Model: WDC WD5000AAKS-0
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 2D86DB2C-8285-4483-88D1-EDAF06E991C5
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 976773134
Partitions will be aligned on 2048-sector boundaries
Total free space is 2029 sectors (1014.5 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   EF00  EFI System Partition
   2         1050624       976773119   465.3 GiB   8300

「元のディスク」のパーティション情報のままなので色々と辻褄が合ってません。
ですが、パーティション情報の残滓は確認できたので、これを修復していきます。

(2) パーティションテーブルの回復

先ずは testdisk を使用して、パーティションテーブルを回復します。

$ sudo apt install testdisk
$ sudo testdisk

対話形式の画面になるので、次の手順で操作します。

  1. [ Create ] を選択。 ※ログファイル生成
  2. カーソルキーで Disk /dev/sdc に移動し、[Proceed ] を選択。
  3. Disk /dev/sdc の情報表示。[ Continue ] を選択。
  4. [EFI GPT] を選択。
  5. [ Analyse ] を選択。
  6. とりあえず [Quick Search]を選択。
  7. 結果が「元のディスク」と同じパーティション構成なのを確認して q を押下。
  8. [ Write ] を選択。
  9. 「Write partition table, confirm ? (Y/N)」と表示されるので y を押下。
  10. 「You will have to reboot for the change to take effect.」と表示されるので [OK] を選択。
  11. [ Quit ] を選択。
  12. [    Quit    ] を選択して、testdisk を終了。

ここで一旦、作業していた OS を再起動します。

※この時点で「復旧用ディスク」の EFI パーティションが認識され、起動可能デバイスの対象になりますが、まだ起動できません。肝心の ext4 パーティションに不整合があるためです。

Ubuntu 20.04 (/dev/sdb) が再起動したら、もう一度 sfdisk と gdisk を実行します。

パーティションテーブルが回復したので、今度はエラーがあるのものの、それなりにパーティション情報が表示されるはずです。

(3) パーティションの不整合

改めて gdisk で「復旧用ディスク」の状態を確認します。

$ sudo gdisk -l /dev/sdc 
GPT fdisk (gdisk) version 1.0.5

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.

Warning! Secondary partition table overlaps the last partition by
2098 blocks!
You will need to delete this partition or resize it in another utility.
Disk /dev/sdc: 976771055 sectors, 465.8 GiB
Model: WDC WD5000AAKS-0
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 2D86DB2C-8285-4483-88D1-EDAF06E991C5
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 976771021
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   EF00  EFI System Partition
   2         1050624       976773119   465.3 GiB   8300

利用可能セクタの末尾が「復旧用ディスク」本来の 976771021 になりました。

しかし、パーティション 2 の終了セクタは「元のディスク」のままです。
容量の小さい「復旧用ディスク」には存在しないセクタ番号を指しているため、このままでは ext4 ファイルシステムとしてマウントできません。

sfdisk でも駄目な事が分かります。

$ sudo sfdisk -V /dev/sdc
/dev/sdc:
パーティション 2 はディスクに比べて大きすぎます。
エラーが 1 個検出されました。
(4) 不整合の解消

パーティション 2 の終了セクタが 976771021 以内を指すように調整してみます。

parted を使用して、対話形式で確認(print)しながら修正します。
正確にセクタ番号を指定したいので、処理はセクタ単位(unit s)で行います。

$ sudo parted /dev/sdc
GNU Parted 3.3
/dev/sdc を使用
GNU Parted へようこそ! コマンド一覧を見るには 'help' と入力してください。
(parted) unit s                                                           
(parted) print                                                            
エラー: ディスクの外側にパーティションは作れません。
無視(I)/Ignore/取消(C)/Cancel? i                                          
モデル: ATA WDC WD5000AAKS-0 (scsi)
ディスク /dev/sdc: 976771055s
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt
ディスクフラグ: 

番号  開始      終了        サイズ      ファイルシステム  名前                  フラグ
 1    2048s     1050623s    1048576s    fat32             EFI System Partition  boot, esp
 2    1050624s  976773119s  975722496s  ext4

(parted) resizepart                                                       
パーティション番号? 2                                                     
終了?  [976773119s]? 976771021s                                           
警告: パーティションを縮小するとデータを失うかもしれませんが、それでも実行しますか?
はい(Y)/Yes/いいえ(N)/No? y                                               
(parted) print                                                            
モデル: ATA WDC WD5000AAKS-0 (scsi)
ディスク /dev/sdc: 976771055s
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: gpt
ディスクフラグ: 

番号  開始      終了        サイズ      ファイルシステム  名前                  フラグ
 1    2048s     1050623s    1048576s    fat32             EFI System Partition  boot, esp
 2    1050624s  976771021s  975720398s  ext4

(parted) quit                                                             
通知: 必要であれば /etc/fstab を更新するのを忘れないようにしてください。
$

これで「復旧用ディスク」に適合したパーティション情報になりました。
強引に上書きして辻褄が合わなかった部分は解消されたはずです。

(5) ファイルシステムの回復

続いて パーティション 2 のファイルシステムを回復します。

/dev/sdc のパーティション操作を反映して、/dev/sdc2 の ext4 ファイルシステムを調整します。

$ sudo partprobe /dev/sdc
$ sudo resize2fs -f /dev/sdc2
resize2fs 1.45.5 (07-Jan-2020)
Resizing the filesystem on /dev/sdc2 to 121965049 (4k) blocks.
The filesystem on /dev/sdc2 is now 121965049 (4k) blocks long.

$ sudo fsck /dev/sdc2
fsck from util-linux 2.34
e2fsck 1.45.5 (07-Jan-2020)
/dev/sdc2: clean, 660856/30498816 files, 93048098/121965049 blocks

ようやく整合性が取れたディスクになりました。

$ sudo gdisk -l /dev/sdc
GPT fdisk (gdisk) version 1.0.5

Partition table scan:
  MBR: protective
  BSD: not present
  APM: not present
  GPT: present

Found valid GPT with protective MBR; using GPT.
Disk /dev/sdc: 976771055 sectors, 465.8 GiB
Model: WDC WD5000AAKS-0
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 2D86DB2C-8285-4483-88D1-EDAF06E991C5
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 976771021
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   EF00  EFI System Partition
   2         1050624       976771021   465.3 GiB   8300  
$ sudo sfdisk -V /dev/sdc
/dev/sdc:
エラーは検出されませんでした。
ヘッダバージョン: 1.0
128 個のパーティションのうち、 2 個を使用しています。
合計 2014 個の空きセクタが 1 セグメント(最大 1007 KiB)内に、あります。

特にエラーがなければ、復旧作業は以上です。

後は PC を再起動して /dev/sdc の Ubuntu 18.04 を起動してみます。

3. 所感

HDD の不調から復旧作業を試みましたが、なかなか大変でした。

パーティションに不整合というか矛盾があると、普段利用してるツール類が悉く使えないなんて...ちょっとだけパーティションがはみ出しただけなのに!

移行が必要な場合、容量がより大きなディスクに退避してたし、SSD とか小容量の場合は新規に OS をイントールしてたので、全く気づきませんでした。

エラーがあっても parted でパーティションを縮小できるのに気づくまで、ホント無駄に試行錯誤してましたよ。成功して良かったです。

これで不良ブロックが存在してたらどんなに大変だったんだろう。
dumpfs とか使う日が来たりして...

その後、クローンしたディスクは無事に動作してます。
移行も済んだので、このまま経過観察しようと思います。