partedで間違えて削除したパーティションを復旧する

 先日、外付けディスクに新規作成したパーティションext4で初期化しようとしたところ、"The resulting partition is not properly aligned for best performance."と言われたため、パーティションを切りなおそうと、partedで既存パーティションの削除・再作成を行おうとしました。
 ところが、誤って異なるディスクに対してパーティション削除を行ってしまい、復旧する必要があったので、以下に記録しておきます。
 

誤ってパーティション削除

 /dev/sdcに対してパーティション削除を行いたかったのですが、/dev/sdaに対して削除を行ってしまいました。
 というのも、partedは引数無しで起動すると、デフォルトでは/dev/sdaが選択されるようです。

$ sudo parted
GNU Parted 3.2
Using /dev/sda ←ここに/dev/sdaと表示されているのに見落とした
Welcome to GNU Parted! Type 'help' to view a list of commands.

 また、本来の対象ディスクも誤って削除したディスクもSeagate Expansion Deskだったために、違和感を覚えずに作業を進めてしまいました。

(parted) print free
Model: Seagate Expansion Desk (scsi)
Disk /dev/sda: 2000GB
Sector size (logical/physical): 512B/4096B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
        32.3kB  1049kB  1016kB           Free Space
1      1049kB  2000GB  2000GB  primary  ext4

 partedのヘルプを確認しておくと、rmにパーティション番号を指定すると当該パーティションを削除できることが判ります。

(parted) help
  align-check TYPE N                        check partition N for TYPE(min|opt) alignment
  help [COMMAND]                           print general help, or help on COMMAND
  mklabel,mktable LABEL-TYPE               create a new disklabel (partition table)
  mkpart PART-TYPE [FS-TYPE] START END     make a partition
  name NUMBER NAME                         name partition NUMBER as NAME
  print [devices|free|list,all|NUMBER]     display the partition table, available devices, free space, all found
        partitions, or a particular partition
  quit                                     exit program
  rescue START END                         rescue a lost partition near START and END
  resizepart NUMBER END                    resize partition NUMBER
  rm NUMBER                                delete partition NUMBER
  select DEVICE                            choose the device to edit
  disk_set FLAG STATE                      change the FLAG on selected device
  disk_toggle [FLAG]                       toggle the state of FLAG on selected device
  set NUMBER FLAG STATE                    change the FLAG on partition NUMBER
  toggle [NUMBER [FLAG]]                   toggle the state of FLAG on partition NUMBER
  unit UNIT                                set the default unit to UNIT
  version                                  display the version number and copyright information of GNU Parted

 で、対象ディスクが異なっていることに気づかないまま、パーティション削除してしまったのです。が、何やらエラーメッセージが表示されました。「使用中のパーティションを書き換えたけど、カーネルにそれを通知できないから古いパーティションは使用中のまま残ってしまうぞ。追加の変更を行う前に再起動するべきだぞ。」みたいなことを言っています。ここで、対象ディスクを間違えていたことに気づいたため、Cancelを選択しました。

(parted) rm 1
Warning: Partition /dev/sda1 is being used. Are you sure you want to continue?
Yes/No? y
Error: Partition(s) 1 on /dev/sda have been written, but we have been unable to inform the kernel of the change,
probably because it/they are in use.  As a result, the old partition(s) will remain in use.  You should reboot now
before making further changes.
Ignore/Cancel? c

 が、すでに時遅し。全領域がFree Spaceとして認識されています。

(parted) print free
Model: Seagate Expansion Desk (scsi)
Disk /dev/sda: 2000GB
Sector size (logical/physical): 512B/4096B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type  File system  Flags
        32.3kB  2000GB  2000GB        Free Space

 

rescueコマンドで復旧を試行

 先ほど叩いたpartedのrmコマンドは数秒とかからず実行されました。実データを削除するには短すぎますので、パーティションテーブルというか、管理情報のメタデータだけが変更されたと考えられます。故に、現状では復旧できる可能性はかなり高いはずです。
 調べてみると、partedのマニュアルには間違えてrmコマンド叩いてもrescueコマンドで復旧できるようなことが書かれています。
Parted User’s Manual: rescue

 間違えてrmを叩いてしまったpartedのセッションは開いたままですので、そこでrescueを実行してみます。rescueの引数に、ディスクのどこから復旧できるパーティションを探すのかを指定する必要があるので、全領域を指定する意味で0から2000Gを指定してみましたが、全領域がFree Spaceのままです。

(parted) rescue
Start? 0
End? 2000G
(parted) print free
Model: Seagate Expansion Desk (scsi)
Disk /dev/sda: 2000GB
Sector size (logical/physical): 512B/4096B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type  File system  Flags
        32.3kB  2000GB  2000GB        Free Space

 
 続いて、引数の指定方法を変えて、0%から100%を指定してみましたが、状況は変わらず。

(parted) rescue
Start? 0%
End? 100%
(parted) print free
Model: Seagate Expansion Desk (scsi)
Disk /dev/sda: 2000GB
Sector size (logical/physical): 512B/4096B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type  File system  Flags
        32.3kB  2000GB  2000GB        Free Space

 
 誤ってrmを叩いたときに表示されたメッセージのことを思い出すと、カーネルが認識している情報とディスクの現状に齟齬があるためにrescueできないのかと思い、再起動*1してから再度rescueコマンドを叩いてみても状況は変わりませんでした。
 

testdiskで復旧

 他の復旧手段を調べてみると、testdiskというツールがあるようです。Ubuntuでは標準ではインストールされていませんが、パッケージマネージャから導入可能です。

sudo apt install testdisk

 testdiskを起動すると対話型UIとなっており、基本的には画面の指示通り選択するだけです。最後に再起動したところ、無事復旧できたようで元のデータにアクセスできました。
 スクリーンショットを撮っていないので雑な説明ですが、testdiskのUIで迷う点があるとすればPartition table typeの選択でIntelを選ぶことくらいでしょうか。

 なお、復旧後のディスクにparted -lを叩いてみると、ディスクの外側にパーティションがあるみたいなエラーメッセージが表示されました。データにはアクセスできても、管理情報の一部は不完全な状態なのかもしれません。この状態で書き込み続けるのは怖いので、いったん別のディスクに復旧したデータを移動したうえで、初期化しなおしてからデータを書き戻した方が良さそうです。
 

まとめ

  • partedを引数無しで起動すると、デフォルトで/dev/sdaが対象ディスクとして選択されているので、誤操作に注意が必要
  • partedで誤ってrmしてもrescueで復旧ができることもあるらしい
  • partedのrescueが上手く機能しなくても、testdiskで復旧できることがある

 



以上。

*1:当該ディスクが自動マウントされないよう、再起動前にfstabを編集しています。