Raspberry PiをUSB(HDD)で起動させる
2020/02/05
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
です。
パーティションの切り分け方や接続しているデバイスによってはsda2
やsdb3
など他の値の可能性もあるので要注意。
以下は/dev/mmcblk0p2
から/dev/sda1
にddする例。
sudo dd if=/dev/mmcblk0p2 of=/dev/sda1 bs=32M conv=noerror,sync status=progress
ここでif
やof
の指定を間違えると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-02
をPARTUUID=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パーティションに入っていたファイルをコピーするだけです。
もちろん今使っている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
を使用していないので使えません。
この方法でブートさせるメリットはほとんどないので、個人的にはあまり使わない方法かなと。