なうびるどいんぐ

脳みそ常時-3dB

Raspberry PiをUSB(HDD)だけで動かす(SD不要)

      2020/02/05    HimaJyun

Raspberry PiをUSB(HDD)で起動させる」というやり方は既にあります。

しかし、これは単にデータ(OS)の部分をHDDに移しただけであり、依然としてブートローダとなるSDカードは必要でした。

比較的新しめのRaspberry Piでは、ブートローダーとなるSDカードすら使わずにUSBストレージだけで起動させられるみたいなので試してみました。

スポンサーリンク

木苺、USBで動く。

Raspberry Pi 2B(v1.2以上)、3A+、3B、3B+でないと出来ないみたいです。(4Bはブートローダーが変更されたので2020/02/04の時点では利用不能、実装予定はアリ)

3B+未満の場合は準備が完了するまでSDカードが必要になります。

OSはRasbianです。それ以外のディストリで出来るかは不明、NOOBSでインストールした場合は一筋縄では行かないかも……(というかNOOBSってそういう使い方するものじゃないよね?ないのか?)

木苺の下ごしらえ

2B v1.2や3Bの場合はデフォルトだとUSBブートが有効化されていないので、まず最初にUSBブートを有効にする必要があります。(3B+ではデフォルトで有効なのでスキップして構いません)

早い話が以下のコマンドをコピペで実行していけばOK

# USBブートを有効にする
echo "program_usb_boot_mode=1" | sudo tee -a /boot/config.txt

# タイムアウトを5秒にする(HDDの場合は多分必要)
echo "program_usb_boot_timeout=1" | sudo tee -a /boot/config.txt

# 再起動(再起動した段階で変更がハードに書きこまれる)
sudo reboot

再起動した後に「vcgencmd otp_dump | grep 17:」を実行して「17:3020000a」となっていれば設定完了。

公式のドキュメントでは書かれていなかったが、USB HDDを使う場合「program_usb_boot_timeout」を設定しないときっと動きません。

これはタイムアウトをデフォルト(2秒)から5秒に引き延ばすためのオプションです。

HDDはスピンアップが必要なので、デフォルトの2秒ではきっとタイムアウトしてしまって起動しません。(場合によってはこの5秒でも足りなかったりするのですが……)

ちなみに、これらの設定はOTPと言って、一度書き込むと元に戻せません。つまり一度USBブートを有効にすると無効には戻せない。

2Bや3Bでは有効にしても今まで通り使えるので問題ありません。3A+のみ注意、有効にするとUSBデバイスモードという物が利用できなくなります。

新規インストールの場合 (推奨)

新規でインストールする場合はとても簡単です。

SDカードにRaspbianを書き込むのと同じです。今までであれば書き込み先にSDカードを指定していた所を、USBデバイスに変更するだけです。
書き込み先にUSBデバイスを指定(画像はbalenaEtcherで500GBのUSB HDDに書き込む例)

要するにUSBデバイスに直接Raspbianのimgを書き込んでしまってOKって訳です。別にこれSDカード専用って訳じゃないんだよ。

あとはSDカードと同じです。ヘッドレスで起動させる場合は「boot」パーティションに「ssh」ファイルを作成したりする、その辺まで含めて同じです。

やる事はこれだけ。準備が出来たらSDカードを抜いて、USBデバイスだけを刺した状態にして起動しましょう。

動くなら動くし、動かないなら動かない。

「新規インストールでしか使えない」「パーティションを切れない」という欠点はありますが、とても簡単です。普段はこちらの方法で十分でしょう。

注意点

注意点ですが、Windows+USB HDDの場合はそのままだと「boot」が表示されないので、「ディスクの管理」からドライブ文字を割り当ててやる必要があります。
ドライブ文字の割り当て

それから、USB-HDDを利用する場合はSATA->USB変換アダプタ(HDDケース)との相性があるのか、上手く行く変換アダプタと全く動かない変換アダプタがありました。

上手く行かない場合は別の変換アダプタを試してみましょう。

既存の環境から変換

「パーティションを細かく分けたい」「既存の環境をUSB化したい」という場合は少し面倒になります。

既存の環境を起動したままデータをコピーするので、MySQLみたいなディスクにデータを書き込むプロセスがあるのならあらかじめ停止しておくのが吉です。

あと、こちらは古い手法なので特別な理由がないのなら上記の新規インストールでimgをUSBに書き込む方法を強く推奨。

(もしかするとこんな複雑な手順を踏まなくても、他のPCでSDカードからUSBデバイスにddしても動くかもしれない、試してない)

パーティションを作成する

まずはUSBをPiに接続し、パーティションを作成します。

パーティションは好きなように切って構いませんが、USBデバイスの先頭にFAT32のブートパーティションが必要になります。

USBをPiに刺すと、他に余計な物を繋いでいない限り「/dev/sda」として認識されるはずです。

「sudo parted /dev/sda」でパーティションの作成に移ります。

partedが入力待ちになったら、パーティションを切りましょう。以下はUSBデバイス全体を使用する例。

GNU Parted 3.2
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) mktable msdos
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? Yes
(parted) mkpart primary fat32 0% 100M
(parted) mkpart primary ext4 100M 100%
(parted) print
Model: Logitec Corp. LHR (scsi)
Disk /dev/sda: 320GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags:

Number  Start   End     Size    Type     File system  Flags
 1      1049kB  99.6MB  98.6MB  primary  fat32        lba
 2      99.6MB  320GB   320GB   primary  ext4

(parted) quit

コピペ用、以下の内容をコピペすればOK

mktable msdos
Yes
mkpart primary fat32 0% 100M
mkpart primary ext4 100M 100%
print
quit

でもって、パーティションをフォーマットする。

sudo mkfs.vfat -n BOOT -F 32 /dev/sda1
sudo mkfs.ext4 /dev/sda2

もちろんUSB上のデータは既存パーティションを維持しない限り全て消えるので、可愛い可愛い彼女(そんなものは居ない)の誕生日映像みたいなのをうっかり消してしまわないように注意しましょう。

(もっとも、先頭にFAT32が必要な関係から既存パーティションを消さずにパーティションを切るのは難しいと思いますが……)

データのコピー

データはrsyncで移す模様、rsyncが入っていない場合は入れる。

sudo apt-get install -y rsync

マウントしてからrsyncでコピーする。

sudo mkdir -p /mnt/target
sudo mount /dev/sda2 /mnt/target/
sudo mkdir /mnt/target/boot
sudo mount /dev/sda1 /mnt/target/boot/
sudo rsync -ax --progress / /boot /mnt/target

マウント先はどこでもOK、今回の例では/mnt/targetを使用しています。

cmdline.txtとfstabの修正

パーティションを作り直した関係からPARTUUIDが変わるので、USB上の/boot/cmdline.txtや/etc/fstabを変更する必要がある。

ちなみに新しいPARTUUIDはls -l /dev/disk/by-partuuid/で確認できる。

該当のファイルをエディターで開いて修正しましょう。(今回の例であれば「/mnt/target/boot/cmdline.txt」と「/mnt/target/etc/fstab」の2つ)

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

(従来までの/dev/sda1などで指定しても問題ない)

SSHホスト鍵の更新

USBで動かす事とは関係ない気がするが……公式のドキュメントではSSHのホスト鍵を更新していたので同じように更新しておく

cd /mnt/target
sudo mount --bind /dev dev
sudo mount --bind /sys sys
sudo mount --bind /proc proc
sudo chroot /mnt/target
rm /etc/ssh/ssh_host*
dpkg-reconfigure openssh-server
exit
sudo umount dev
sudo umount sys
sudo umount proc

その後、シャットダウン(sudo poweroff)して、電源ケーブルを抜いてからSDカードを抜き、もう一度電源を投入する(もちろんUSBは繋いだまま)

上手く行っていればUSBから起動する。

HDDを使う時のコツ

コツというか……

「program_usb_boot_timeout」でタイムアウトを5秒に引き延ばしたが、手元にあるHDDには5秒でもスピンアップしない物があった。

対処法だが、HDDをスピンアップさせたら(HDDが動き始めたのにOSが起動しない状態を確認したら)Raspberry Piの電源を抜いてすぐに入れなおす。乱暴なやり方だが場合によっては上手く行く。

他にも、ケースによってはHDDを「TVモード」のような回転しっぱなしにする設定があったりするので、それを試してみるとか。

あとは電源連動機能のないケース(電源入れてる間HDD回りっぱなしになるような奴)をあえて選ぶとか、省電力機能をオフにしてみるとか……

とにかくスピンアップを間に合わせる必要がある。SSDは何もしなくても上手く行くはず。

どうしてもダメな時は

SDカードをブートローダーとして使用する方法」でやりましょう。

この方法であれば最初にSDカードからブートローダーが読み込まれて、ブートローダー側でHDDがスピンアップするまで待ってくれるので問題ありません。

もっと言えば、SDカードなしだと認識しないUSBデバイスでも利用できる可能性が高い。(ブートローダー側に必要なデバイスドライバなどが含まれているので)

感想

「スピンアップが間に合わない」「そもそも認識しない」という相性系の問題さえクリア出来れば、SDカードすら要らなくなるので便利な方法ではある。

USBメモリやSSDを使用する場合は変換アダプタの相性さえクリアすれば上手く行く可能性は高いでしょう。

HDDの人は素直にSDカードをブートローダー化した方が良いと思います。

 - コンピューター