なうびるどいんぐ

脳みそ常時-3dB

Raspberry PiをUSB(HDD)で起動させる

      2020/02/05    HimaJyun

Raspberry Piをサーバとして利用すると24時間動かす事になりますが、それにSDカードを利用するのは精神衛生上よろしくない。

というわけで、Raspberry PiをUSBデバイス(HDDやSSD)で起動できるようにする方法。

スポンサーリンク

Raspberry PiをUSBで起動

まず最初に、この方法で起動する場合はSDカードが必要です、もちろんUSBデバイスも必要。(USBから先は何でもいいです、フラッシュメモリでもいいし、HDDでもいいし、SSDでもいい)

SDカードを使用しない方法」もありますが、USB-HDDを使用する際にスピンアップが間に合わず起動できない……という事があります。

この記事で紹介する方法はSDカードこそ必要になりますが、安定性や成功率は高いです。用途に合わせてどちらが適しているか決めましょう。

(2020/02/05の時点ではSDカードを使用しない方法はPi 4Bでは利用できないので、4BでUSBから起動させたければこの記事で紹介する方法しか使えません)

ちなみに、この際に使用するSDカードは非常に小さい容量で構いません。128MBとかでも足ります。

パーティションの作成

必要であれば、作業の前にUSBデバイスのパーティションを分割します。

この辺りは個人の好みに合わせて設定して下さい。例としてUSB-HDD(/dev/sda)の全体を使用する場合。

pi@raspberrypi:~ $ sudo parted /dev/sda
GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) mklabel gpt
Warning: The existing disk label on /dev/sda will be destroyed and all data on
this disk will be lost. Do you want to continue?
Yes/No? y
(parted) mkpart primary ext4 0% 100%
(parted) p
Model: Logitec LHR USB Device (scsi)
Disk /dev/sda: 320GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt
Disk Flags:

Number  Start   End    Size   File system  Name     Flags
 1      1049kB  320GB  320GB  ext4         primary

(parted) q
Information: You may need to update /etc/fstab.

コピペ用

mklabel gpt 
y
mkpart primary ext4 0% 100%
p
q

パーティション構成はどんな風にしても構いません。例えばWindowsとデータを共有する時用にNTFSのパーティションを作成するとか。(/はext4にしておく方が無難です)

当然ながらに既存パーティションを消すとデータが消えるのでその事をお忘れなく。

データをコピー (rsync)

/の内容をUSBにコピーします。rsyncでコピーする方法とddでコピーする方法があります。

rsyncを使用すれば必要なファイルだけをコピーするのでddより早く、ディスクの調整も必要なくなります。

(その代わり、特殊なファイルや拡張ファイル属性などの事を考慮する必要があります。確実性重視の方は後述のddでコピーする方法をお勧めします)

まず、使うパーティションをフォーマットしてマウントします。

sudo mkfs.ext4 /dev/sda1
sudo mount -t ext4 -o defaults /dev/sda1 /mnt

後は/から全データをコピーするだけ。

sudo rsync -aHAX --progress / /mnt

これでデータのコピーは完了、ラクチン

データをコピー (dd)

rsyncでコピーした方はこの項目はスキップ。

まず最初に、sudo fdisk -lを実行します、コマンドの結果は以下のようになるはずです(一部端折ってます)

pi@raspberrypi:~ $ sudo fdisk -l
Disk /dev/mmcblk0: 15 GiB, 16088301568 bytes, 31422464 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
Disklabel type: dos
Disk identifier: 0x24e66acb

Device         Boot Start End      Sectors  Size  Id Type
/dev/mmcblk0p1      8192  93813    85622    41.8M c  W95 FAT32 (LBA)
/dev/mmcblk0p2      94208 31422463 31328256 15G   83 Linux

Disk /dev/sda: 298 GiB, 319936614912 bytes, 624876201 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
Disklabel type: gpt
Disk identifier: 00D8E58E-4A6D-452D-840F-0A5B881F4674

Device    Start End       Sectors   Size Type
/dev/sda1 2048  624875519 624873472 298G Linux filesystem

RaspbianのimgをSDカードに書き込んでインストールした場合は/dev/mmcblk0p2がデータを保存しているパーティションになっているはずです。

(NOOBSを使用してインストールした場合は他のパーティションになっている可能性もあるので要注意)

これを、ddを使用して先ほど作成したUSB上のパーティションにコピーします。今回の例であれば/dev/sda1です。

パーティションの切り分け方や接続しているデバイスによってはsda2sdb3など他の値の可能性もあるので要注意。

以下は/dev/mmcblk0p2から/dev/sda1にddする例。

sudo dd if=/dev/mmcblk0p2 of=/dev/sda1 bs=32M conv=noerror,sync status=progress

ここでifofの指定を間違えるとSDカードやUSBのデータが吹っ飛ぶので全神経を研ぎ澄まして実行して下さい。ifのiはInput(入力)のi、ofのoはOutput(出力)のoですよ。

当然ですが、実行するとパーティション(今回の場合は/dev/sda1)のデータはすべて消えるので、可愛い彼女(そんなものは居ない)の大切な大切な大切な誕生日写真などがある場合は退避させておきましょうね。

処理が完了すると以下のように表示されます。

pi@raspberrypi:~ $ sudo dd if=/dev/mmcblk0p2 of=/dev/sda1 bs=32M conv=noerror,sync
477+1 レコード入力
478+0 レコード出力
16039018496 バイト (16 GB) コピーされました、 790.731 秒、 20.3 MB/秒

ddを使用してコピーした場合はファイルシステムのチェックとリサイズが必要になります。

まずはe2fsckでファイルシステムをチェックしましょう。「sudo e2fsck -f <対象のパーティション>」のようにに使用します。

実行すると途中で「Fix<y>?」と尋ねられます。尋ねられなくなるまで「y」をタイプしましょう。

以下、実行例。

pi@raspberrypi:~ $ sudo e2fsck -f /dev/sda1
e2fsck 1.42.12 (29-Aug-2014)
/dev/sda1: recovering journal
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
Free blocks count wrong (3613733, counted=3613700).
Fix<y>? y

/dev/sda1: ***** FILE SYSTEM WAS MODIFIED *****
/dev/sda1: 35738/963840 files (0.2% non-contiguous), 296956/3910656 blocks

このままでは単にUSBにパーティションをコピーしただけです。なのでパーティションの容量もSDカードと同じままです。

resize2fsでパーティションを拡張しましょう。「sudo resize2fs <対象のパーティション>」のように使います。

以下、実行例。

pi@raspberrypi:~ $ sudo resize2fs /dev/sda1
resize2fs 1.42.12 (29-Aug-2014)
Resizing the filesystem on /dev/sda1 to 488378368 (4k) blocks.
The filesystem on /dev/sda1 is now 488378368 (4k) blocks long.

これでUSBの準備が完了。

要するに「ddでコピーして」「e2fsckして」「resize2fsする」ということ。

fstabの更新

今のままではルートディレクトリにSDカードを使用する設定になったままなので、これを変更しておかないと起動できなくなります。

まずはPARTUUIDを確認しましょう。ls -l /dev/disk/by-partuuid/で確認できます。このPARTUUIDは後から必要になるのでメモしておきましょう。

pi@raspberrypi:~ $ ls -l /dev/disk/by-partuuid/
total 0
lrwxrwxrwx 1 root root 15 Aug 30 07:21 24e66acb-01 -> ../../mmcblk0p1
lrwxrwxrwx 1 root root 15 Aug 30 07:21 24e66acb-02 -> ../../mmcblk0p2
lrwxrwxrwx 1 root root 10 Aug 30 07:22 52a973b2-092f-4ac0-9086-ee7f9cd69795 -> ../../sda1

次に、USBを適当な場所にマウントしましょう。

例として/dev/sda1/mntにマウントする場合。

sudo mount -t ext4 -o defaults /dev/sda1 /mnt

でもって、USB上の/etc/fstabを開きます。今回は/mntにマウントしたので/mnt/etc/fstabですね。

proc            /proc           proc    defaults          0       0
PARTUUID=24e66acb-01  /boot           vfat    defaults          0       2
PARTUUID=24e66acb-02  /               ext4    defaults,noatime  0       1
# a swapfile is not a swap partition, no line here
#   use  dphys-swapfile swap[on|off]  for that

ルートディレクトリ(/)のPARTUUIDを先ほど確認したPARTUUIDに書き換えます。

今回の例であれば、PARTUUID=24e66acb-02PARTUUID=52a973b2-092f-4ac0-9086-ee7f9cd69795に変更する、という事。

また、SDカードを他の物に変更する場合は/bootのPARTUUIDが予測できなくなるので、/dev/mmcblk0p1で指定します。

proc            /proc           proc    defaults          0       0
/dev/mmcblk0p1  /boot           vfat    defaults          0       2
PARTUUID=52a973b2-092f-4ac0-9086-ee7f9cd69795  /               ext4    defaults,noatime  0       1
# これでもOK
#/dev/sda1  /               ext4    defaults,noatime  0       1

(もちろん、今刺しているSDカードをそのまま使用する場合は/bootの方は編集しなくてもOKです)

これでPi側での作業は終わりです、シャットダウンしましょう。

SDカードをコピー (必要に応じて)

ブートローダーのためだけに容量の大きなSDカードを使うのはもったいない……という人は適当なSDカードにブートローダーをコピーしましょう。

新しいSDカードをFAT32でフォーマットして、Raspberry PiのSDカードのbootパーティションに入っていたファイルをコピーするだけです。raspberrypi-usb-boot-007

もちろん今使っているSDカードをそのまま使用してもOK。

cmdline.txtを編集

ブートローダーの入ったSDカードをPCに接続して、cmdline.txtを編集します。メモ帳(notepad.exe)で編集して構いません。

(SDカードをそのまま使うつもりの場合はRaspberry Pi上から直接/boot/cmdline.txtを編集してもOK)

ファイル内にSDカードのPARTUUIDを指定している部分があるので、それをUSBのPARTUUIDに書き換えます。

これで出来上がりです。ブートローダーの入ったSDカードとUSBデバイスを接続して起動してみて下さい。

起動してみる

あとは電源を入れて祈るだけ。動くなら動くし、動かないなら動かない。

初回起動時にディスクのチェックが走る事があるので、もし何かディスクを読み書きしている様子であればしばらく待ってみましょう。

起動出来ない場合はディスプレイを接続すると起動処理の際にエラーが出てくれるはずなので原因の特定を。

少し手順が複雑なので、慣れるまでは難しいかも……

USBデバイスに相性がある

USB-HDDとかで多いみたいですが、USBデバイス(変換アダプタやHDDケース)との相性問題が起きることがあります。

最初から認識しておらず起動しないなら分りやすいのでまだマシ。場合によっては数日ほど付けっぱなしにしているといきなりアクセス出来なくなる物もあります。

特にUSB-HDDとかだと省電力のためにスリープする機能があったりするので、この手の問題は起きやすいかも。

上手く動かない時は相性問題も疑ってみましょう。

余談: USBブートには3種類ある

Raspberry PiをUSBブートさせる方法には「SDカードでカーネルまで起動して、ルートディレクトリにUSBを使用する方法 (この記事で紹介した方法)」と「USBだけで起動させる方法」の2種類があります。

それとは別に、実はその中間のような「ブートローダーにSDカードを使用するが、カーネルとルートディレクトリはUSBを使用する方法」もあります。

これら3つの方法は「どの段階からUSBを使用するのか?」という事の違いになるのですが、基本的には前者の2つが選択肢になるので「ブートローダーにSDカード、カーネルとルートディレクトリはUSB」の方法は覚えなくても良いと思います。

覚える必要はないでしょうが、違いを理解しておく方が良いと思うので念のため説明。

SDカードでカーネル起動、ルートにUSB

今回この記事で紹介した方法です。

SDカード上のブートローダーを読み込み、次にSDカード上のカーネルをロード、ルートディレクトリにはUSBを使用する方法です。

そのため、ブートローダー(/boot/bootcode.bin)とカーネル(/boot)にはSDカードを使用します。ルートディレクトリ(/)だけがUSBになります。

/はUSBになりますが、/bootは依然としてSDカードが使用されます。

なので、SDカードが必要です。

この方法はブートの仕組みが通常のSDカード利用時と一緒なので、Raspberry Piの種類問わず使えます。

USBだけで起動

これは「Raspberry PiをUSB(HDD)だけで動かす(SD不要)」で解説している方法。

最初からUSBを使用してブートローダーを読み込み、カーネルもUSBの物を使用し、ルートディレクトリにもそのままUSBを使用する方法です。

ブートローダー(/boot/bootcode.bin)、カーネル(/boot)、ルートディレクトリ(/)のすべてでUSBを使用しています。

なので、SDカードは不要です。

最初からUSBを使用する関係から、ハードウェア側の対応が必要になります。比較的新しいRaspberry Pi(2B v1.2、3A+、3B、3B+)が必要になります。

(Raspberry Pi 4Bはブートの仕組みが変更された関係から、2020/02/05の時点ではこの方法は使えません。実装予定はアリ)

SDカードでブート、カーネルとルートはUSB

前者2つの方法の中間。

ブートローダーはSDカードから読み込みますが、カーネルはUSBの物を使用、ルートディレクトリにも続けてUSBを使用する方法です。

そのため、ブートローダー(bootcode.bin)にはSDカードを使用しますが、カーネル(/boot)とルートディレクトリ(/)にはUSBを使用します。

(ちなみに、その状態で起動したOSから見た/boot/bootcode.binはUSB上のもので、これは利用されていません。マウントされていない/dev/mmcblk0p1に入っているbootcode.binが使用されています。)

なので、SDカードが必要です。

Raspberry Pi4以前であれば使える方法です。Raspberry Pi4はそもそもbootcode.binを使用していないので使えません。

この方法でブートさせるメリットはほとんどないので、個人的にはあまり使わない方法かなと。

 - コンピューター ,