概要
本記事は、Raspberry Pi 4でOS等の主要データを格納していたmicroSDが壊れて起動しなくなった後で、新しいmicroSDにデータをコピーして運良く復旧できた内容についてまとめたものです。
事の発端
ラズパイに突然アクセスできなくなる...
Raspberry Pi 4をおおよそ二年ほど、常時稼働させていました。用途の一つとして、自分で作ったDockerイメージを格納するためのコンテナレジストリのサーバ稼働用として使っていました。OSはUbuntu 22.04 LTSです。
ある時、別のマシンで作ったコンテナイメージをラズパイのコンテナレジストリにdocker push
していたら、突如処理が止まってしまいます。原因特定のため、ping
やssh
やnmap
のコマンド達を実行してみるも、つながっている感じのレスポンスはどれも返ってこない状態です...
ラズパイはWi-Fi接続で使っていたので、「おそらくネットワークの調子が悪いのかな」と推測します。ラズパイの現在の状態を確認できる手段があればいいのですが、普段はモニターを接続せずに使っていてすぐには確認できないです。初期設定だと、電源が入っている状態でモニターを後でつないでも画面には何も映らない設定になっています。
なので仕方なく、電源スイッチを切ってモニターをつないだ後に、再び電源スイッチを入れて再起動することにします。
ラズパイが起動しない...
電源を入れて1分くらい待つと、以下のように怪しい表示が出てきます。
以下、主要なメッセージを抜粋。
superblock needs_recovery flag is clear, but journal has data.
Run journal anyway
UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.
fsck exted with status code 4
The root filesystem on /dev/mmcblk0p2 requires a manual fsck
どうやら/dev/mmcblk0p2
のファイルシステムに重要な問題があり自動復旧できなくて、手動での修復が必要のようです。
fsck
はファイルシステムのチェックや修復に使うという認識は何となくありましたが、実際に使ったことはありません。若干不安ではありますが、言われた通りにfsck
を実行してみることにします。
ところが、unable to set superblock flags on writable
(writable
というデバイスのsuperblock flagsを設定できませんでした)と表示されて修復できなかったようです。うーんこれは結構厳しい...
※余談ですが、最初筆者は上の意味を「superblock flagsがwritableな状態にならなかった」と誤解していました。後に、writable
は/dev/mmcblk0p2
のパーティションに付けられたラベルの名前だったことに気づきます。なので素直に「writable
というデバイスのsuperblock flagsを設定できませんでした」と理解すればよかったのです。(出ている単語に引っ張られて誤訳してしまう自分が嫌だw)
復旧のための作戦と準備
新しいmicroSDカードにコピーして復旧する方針に
ラズパイのOS本体が入っているmicroSDカードはもう寿命だなと判断して、新しいmicroSDカードを買ってそちらにデータをコピーすることにします。実際にmicroSDカードのデバイスの状況を診断ツールとかで確認したわけではないので本当はまだ使えたかもしれませんが、そこを頑張るメリットはほぼないので「もう寿命」と判断しました。
新しいmicroSDカードとして購入したのは、SanDiskの128GBのストレージを格納できるもの(型番はSDSQUAB-128G-GH3MA、リンク)です。
また、データをコピーするためのLinux PCをラズパイとは別に用意します。幸いなことに私が持っていたPCはSDカードの差し込み口があったので、microSDからSDへの変換アダプターさえあればデータをコピーできそうです。(もしSDカード差し込み口がない場合は、SDカードリーダを買う必要があります)
復旧手順を考える
復旧に必要なモノの準備が整ったので、次は手順を考えます。以下のような感じでやっていきます。
1. microSDカードのデータを、PCにコピー
1-1. 今まで使っていたmicroSDカードを、コピー用のPCに取り付ける
1-2. microSDカードのデータをPCにコピーする
1-3. 今まで使っていたmicroSDカードをPCから取り外す
2. PCにコピーしたデータを、新しいmicroSDカードにコピー
2-1. 新しいmicroSDカードを、コピー用のPCに取り付ける
2-2. 新しいmicroSDカードにパーティションを作成する
2-3. PCにコピーしたデータを新しいmicroSDカードにコピーする
2-4. 新しいmicroSDカードをPCから取り外す
3. ラズパイの起動
新しいmicroSDカードをラズパイに差し込んで、祈りながら電源スイッチを入れる
ここで一番心配なのは、「1-2. microSDカードのデータをPCにコピーする」の部分です。そもそもファイルシステムが異常な状態になっているのに、まともにコピーできるのだろうか...
まあともかくやってみましょう。
復旧していく
考えた復旧手順をもとに、復旧を目指して実作業を進めていきます。
1. microSDカードのデータを、PCにコピー
1-1. 今まで使っていたmicroSDカードを、コピー用のPCに取り付ける
microSDカードを取り付けた後に、現在のデバイスの状態を確認してみます。
(後で新しいmicroSDカードでパーティションを作成する際にセクターで範囲指定したいので、unit s
でセクターで表示しています)
$ sudo parted /dev/mmcblk0 unit s print
モデル: SD SC128 (sd/mmc)
ディスク /dev/mmcblk0: 128GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos
ディスクフラグ:
番号 開始 終了 サイズ タイプ ファイルシステム フラグ
1 2048s 526335s 524288s primary fat32 boot, lba
2 526336s 249737182s 249210847s primary ext4
パーティションが二つに分かれていて、/dev/mmcblk0p1
はブート用、/dev/mmcblk0p2
はOS本体が格納されている領域のようです。先ほどラズパイを起動した時に問題があると言われたのは、/dev/mmcblk0p2
のパーティションでした。
1-2. microSDカードのデータをPCにコピーする
上で確認した各パーティションのデータをそれぞれコピーします。コピーするためにはOSにマウントが必要なので、次のコマンドでマウントしてOSから各ファイルシステムにアクセスできる状態にしておきます。
sudo mkdir /mnt/src1 /mnt/src2
sudo mount /dev/mmcblk0p1 /mnt/src1
sudo mount /dev/mmcblk0p2 /mnt/src2
問題があると言われた /dev/mmcblk0p2
もあっさりとマウントできました。不安なので、中身もざっくり確認してみます。
$ ls -l /mnt/src2/
合計 116
drwxr-xr-x 24 root root 4096 1月 28 16:08 ./
drwxr-xr-x 12 root root 4096 8月 15 2023 ../
drwxr-xr-x 2 root root 4096 4月 19 2022 .disk/
lrwxrwxrwx 1 root root 7 4月 19 2022 bin -> usr/bin/
drwxr-xr-x 4 root root 4096 3月 24 08:41 boot/
drwxr-xr-x 2 root root 4096 8月 17 2022 config/
drwxr-xr-x 2 root root 4096 8月 17 2022 data/
drwxr-xr-x 4 root root 4096 4月 19 2022 dev/
drwxr-xr-x 122 root root 12288 3月 24 08:34 etc/
drwxr-xr-x 5 root root 4096 1月 29 2023 home/
...
おお普通に見れている!安心するのは早いですが、とりあえずはよかった。
続いてコピー用のディレクトリを作ります。
sudo mkdir -p /path/to/copy1
sudo mkdir -p /path/to/copy2
↑ ディレクトリ名はお使いの環境に応じて変更ください
作ったディレクトリに、rsync
コマンドでデータをコピーしていきます。
まずは /dev/mmcblk0p1
から。
sudo rsync -ahv /mnt/src1/ /path/to/copy1/
10秒もかからずに終わりました。
容量を確認すると237MBなので、25MB/sくらいの速さでコピーできていそうです。
$ sudo du -sh /path/to/copy1
237M /path/to/copy1
続いては、ファイルシステムた異常になっている問題の/dev/mmcblk0p2
のコピーです。確か容量は40GBよりちょっと少ないくらいだったので、30分もあればコピーが終わると予想し、以下のコマンドでコピーを実行します。
sudo rsync -ahv /mnt/src2/ /path/to/copy2/
ところが1日以上経ってもrsyncが完了せず、ずっと続いています。
そして、時折以下のようなエラーが出力されます。
rsync: read errors mapping "/mnt/src2/filepath": Input/output error (5)
rsync: readdir("/mnt/src2/dirpath"): Input/output error (5)
途中でrsyncの標準出力が止まってしまうので、処理を一回止めて再実行するというのを数回試します。が、また途中で止まってしまい、結局rsyncは最後まで終了できませんでした...
それでもコピー先のディレクトリやファイル一覧を確認すると、だいだいコピーはできていそうです。完全にrsyncが終わるのを待っていたらどれだけ時間が掛かるかわからないので、「コピーは完了した」とみなして、次のステップに進むことにします。
1-3. 今まで使っていたmicroSDカードをPCから取り外す
以下のコマンドでアンマウントしてから、microSDカードをPCから取り外します。
sudo umount /mnt/src1
sudo umount /mnt/src2
2. PCにコピーしたデータを、新しいmicroSDカードにコピー
2-1. 新しいmicroSDカードを、コピー用のPCに取り付ける
続いて新しいmicroSDカードを取り付けて、現状を確認します。
$ sudo parted /dev/mmcblk0 print
モデル: SD SD128 (sd/mmc)
ディスク /dev/mmcblk0: 128GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos
ディスクフラグ:
番号 開始 終了 サイズ タイプ ファイルシステム フラグ
1 16.8MB 128GB 128GB primary
パーティションテーブルは既にmsdosで作られていて、今まで使っていたmicroSDと同じなのを確認できます。
また、一つのパーティションが既に作られていますが、この後パーティションを作り直す際に邪魔になるので、この時点で次のコマンドで削除しておきます。
$ sudo parted /dev/mmcblk0 rm 1
2-2. 新しいmicroSDカードにパーティションを作成してフォーマットする
今まで使っていたmicroSDと同じようにパーティションとファイルシステムを作成します。
もともとは、次のようなパーティション構成で作られていました。
番号 開始 終了 サイズ タイプ ファイルシステム フラグ
1 2048s 526335s 524288s primary fat32 boot, lba
2 526336s 249737182s 249210847s primary ext4
新しいmicroSDも、上と同じ状態になるようにこれから進めていきます。
パーティションの作成
以下のようにして、2つのパーティションを作成します。mkpart
でパーティションを作成し、set
でパーティション1にboolのフラグをつけています。
$ sudo parted /dev/mmcblk0
(以後はpartedのコマンド入力モードになる)
...
(parted) mkpart primary fat32 2048s 526335s
(parted) set 1 boot on
(parted) mkpart primary ext4 526336s 100%
パーティションが作成されたことを確認して、partedから抜けます。
(parted) p
モデル: SD SD128 (sd/mmc)
ディスク /dev/mmcblk0: 128GB
セクタサイズ (論理/物理): 512B/512B
パーティションテーブル: msdos
ディスクフラグ:
番号 開始 終了 サイズ タイプ ファイルシステム フラグ
1 1049kB 269MB 268MB primary fat32 boot, lba
2 269MB 128GB 128GB primary ext4 lba
(parted) q
ファイルシステムのフォーマット
上の状態だとパーティションが作られただけの状態なので、各パーティションを以下のようにフォーマットします。
sudo mkfs.fat -F32 /dev/mmcblk0p1
sudo mkfs -t ext4 /dev/mmcblk0p2
ラズパイはどうやってブートしている??
ここで一つの疑問が頭をよぎります。
ラズパイが最初に起動した時に、どうやってboot用パーティションやOSルート(/
)の場所を認識するのだろうか...
ブートローダーがGRUBの場合だと、筆者がこちらの記事で書いたように結構面倒な手順が必要です。ラズパイも同じようにやるのでしょうか。
ざっと調べてみると、ラズパイのブートローダーはGRUBではないらしいです。ではその設定とか更新はどうやったらできる??
すぐにわからないので、とりあえずは /etc/fstab
の内容を見てみることにします。
LABEL=writable / ext4 discard,errors=remount-ro 0 1
LABEL=system-boot /boot/firmware vfat defaults 0 1
今まで私が見たことのあるfstabとは異なる点が2つあります。
- (1) マウント元がパーティションのパス(
/dev/sda1
等)やUUIDではなく、LABELで指定されている - (2) マウントポイントに
/boot/firmware
が記載されている
(2)の内容は十分に理解できていませんが、少なくとも(1)のパーティションのラベルづけはやっていた方が良さそうです。
※ 結局ブートローダーの設定や更新の疑問は解決せずに何も対処はしなかったのですが、最終的に起動はできたので結果オーライでした。
各パーティションにラベルをつける
各々次のコマンドでラベルをつけます。ファイルシステムによって使うコマンドが違うようです。
sudo dosfslabel /dev/mmcblk0p1 system-boot
sudo e2label /dev/mmcblk0p2 writable
それぞれのパーティションにラベルが付いたのを確認します。
$ sudo dosfslabel /dev/mmcblk0p1
system-boot
$ sudo e2label /dev/mmcblk0p2
writable
2-3. PCにコピーしたデータを新しいmicroSDカードにコピーする
準備が整ったので、新しいmicroSDカードにデータをコピーします。
まずは、新しいmicroSDカードをマウントします。
sudo mkdir /mnt/dst1 /mnt/dst2
sudo mount /dev/mmcblk0p1 /mnt/dst1
sudo mount /dev/mmcblk0p2 /mnt/dst2
続いて各パーティションのデータをrsyncでコピーします。
sudo rsync -ahv /path/to/copy1/ /mnt/dst1/
sudo rsync -ahv /path/to/copy2/ /mnt/dst2/
/path/to/copy2
に今まで使っていたmicroSDカードからコピーした際は一日経っても終わりませんでしたが、今回は37GBのデータのコピーが22分で終わりました。
2-4. 新しいmicroSDカードをPCから取り外す
以下のコマンドでアンマウントしてから、microSDカードをPCから取り外します。
sudo umount /mnt/dst1
sudo umount /mnt/dst2
3. ラズパイの起動
ようやくラズパイを起動する所まで辿り着きました。データをコピーした新しいmicroSDカードをラズパイに差し込んで、ドキドキしながら電源スイッチを入れます。
コピー処理が完全に終わらなかったり、ブートの仕組みがわからないまま見切り発車でここまで来てしまいましたが、果たして無事に起動できるのでしょうか...
モニターを見てみましょう。
なんと、OSの各サービスの起動の状態まで進んでようです!
そして外付けデバイスの確認エラーは出てますが、ログインを受け付ける状態になったのを確認。
また、別のマシンからping
,nmap
, ssh
してもちゃんと通りました。
運よく復旧できたようです!
起動後の不具合への対処(24/05/10追記)
一応復旧はしてOSは立ち上がるようになったのですが、DNS設定がおかしくなってaptのリポジトリに接続できなくなっていたり、Dockerコンテナが起動しなくなっていたり、不具合があちこちに見られる状態でした。
調べていったら、Systemdが正常に起動していないことが根本原因ということがわかり、以下のコマンドを実行することで解決しました。
sudo apt install --reinstall systemd
これらの不具合の詳細と対処に関しては、以下の記事にまとめました。
おわりに
ディスク系のデバイスに障害が発生した後にOSをクリーンインストールせずに復旧できたのは初めてで、良い経験になりました。クリティカルなディレクトリが異常になっていたら今回のようにOS起動までは辿り着けなかったはずなので、運にも恵まれたと思います。
私の場合は運良く復旧できたのですが、本記事のやり方で復旧できないケースもあるかと思います。その場合は現状からの復旧を諦めて、必要なファイルを(可能な限り)バックアップした上でクリーンインストールして、OSがきれいな状態で必要なパッケージをインストールする等して設定し直していく方がいいかのもしれません。(実は私もOS起動後の不具合の対応に手こずり、クリーンインストールしようかどうかだいぶ葛藤しました)
最後に、今後筆者が可能ならば知りたい内容について書き遺します。
- fsckでファイルシステムを修復できなかった場合に、別の修復手段があるかどうか
- ラズパイ4のブートの仕組み
- ラズパイ4のOSをmicroSDではなくて、USBで接続したSSD等にインストールしてブートする方法