純規の暇人趣味ブログ

首を突っ込んで足を洗う

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

      2018/04/07    HimaJyun

Raspberry Piを利用したサーバ作り、なかなか面白いです。

サーバで利用するとなると漏れなく24時間動かす訳ですが、それにSDカードを利用するのは不安要素があります。

今回はRaspberry PiをUSBで起動する様に(要はOSをUSB接続のHDDに置けるように)してみようと思います。

スポンサーリンク

用意した物

Piそのものは前回の時点で準備出来ているので端折ります。

ddを使ってRaspbianをインストールした前提で進めます、NOOBSとかだとパーティションがちょちょぎれにされているので苦労するかも知れませんが、Googleと仲良くしながら頑張って下さい。

USB(HDD)

HDDで起動させるのがそもそもの目的なのでこれが無いと始まりません。

今回は引き出しに眠っていたHDDを使用します。(HDDの下にあるのが外付けのHDDケースです)
raspberrypi-usb-boot-001

今回はHDDで説明するので文中ではHDDと書いていますが、普通のUSBフラッシュメモリとかでも行けます(それするくらいならSDカードで良い気がしますけどね)

ちなみに読み書きの速度は以下の通り、外付けだとこんな物でしょう。
raspberrypi-usb-boot-002

SDカード

勘違いしている方が多いですが、HDDで起動させるようにしてもSDカードは必要です。

追記:Pi3はSDカードなしで出来る様になりました、「Raspberry Pi 3をUSBストレージだけ(SD不要)で動かす」をご覧下さい。

何故かと言うのを説明するためにはRaspberry Piのブートの仕組みを根掘り葉掘り説明する必要があるので詳しい説明は控えますが、簡単に説明すると「SDカードをブートローダ代わりに利用」しています。

ただ、ブートローダが入るだけなので容量はほんの少しで構いません、128MBでも余裕で足ります。

前回は16GBのSDカードを用意しましたが、流石にこれをブートローダにしてしまうのは勿体無いので転がっていた1GのSDカードを用意しました。
raspberrypi-usb-boot-003

HDDで起動しよう

大まかな流れとしては「1.ddでデータをコピー」「2.ディスクの調整」「3.別のPCでSDカードのデータをコピー」の3ステップです。

接続したHDDは/dev/sda、データを移すパーティションは/dev/sda1だと仮定します。

パーティションの作成

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

この辺りは個人の好みに合わせて設定して下さい、例としてHDD全体を使う場合。

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

当然ながらにディスクの中身は消えるのでその事をお忘れなく。

データをコピー(rsync編)

どうやらrsyncでも出来るみたいです。(細かい動作確認をした訳ではないので、人柱希望の方以外は下のddでコピーする方法をお勧めします。)

rsyncでやれば必要なデータだけをコピーするのでddより早く、ディスクの調整も必要なくなります。

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

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

後は/から全データをコピーするだけ、シンボリックリンクも保持されます。

sudo rsync -ax --progress / /mnt

これでデータのコピーは完了、ラクチン。「fstabの更新」まで読み進めましょう。

データをコピー(dd編)

rsyncでコピーした方は「fstabの更新」まで読み飛ばしてね。

まず最初に、「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

容量的に見て「/dev/mmcblk0p2」がデータを保存しているパーティションのようですね。(この時、NOOBSでのインストールだと細かくちょちょぎれにされているのでどれが実際に利用している物かを探し出す必要があります)

「/dev/sda1」がデータを移すパーティションです、パーティションの切り分け方によってはsda2,sda3……とあるでしょう。

という訳で、「/dev/mmcblk0p2」から「/dev/sda1」にddします。

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

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

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

SDカードの性能に依存しますが、10分ちょい掛かります、しかも不親切な事に処理中は何も出力がありません、超☆エキサイティング!!でもして気長に待っていて下さい。

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

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/秒

ディスクのリサイズと調整

rsyncでコピーした場合は必要ありません。

このまま使えれば幾分か楽なんですけどね、世の中そう甘くないです。

パーティション周りの操作を行ったので、まずはディスクのチェックを行いましょう。

ディスクのチェックは「e2fsck」です、「sudo e2fsck -f /dev/sda1」のように利用します。

実行すると途中で「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

「Fix<y>?」と聞かれなくなるまで実行して下さい、普通は1~3回程度で出来上がるとは思います。

100回やっても1000回やっても–2147483648回やっても「Fix<y>? 」と聞いて来るならきっとそのディスクは逝ってます。

次に、パーティションを拡張しましょう。

先程の状態では単にHDD上にパーティションをコピーしただけです、なのでsda1の容量もSDカードと同じ(今回の場合だと16GB)です。

これでは「いみねーですわよ」なのでパーティションを拡張します「resize2fs」で出来ます。

「sudo resize2fs /dev/sda1」のように使います、これだけです、素晴らしい世界ですね。

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.

次はfstabの更新です。

fstabの更新

今のままではrootとして「/dev/mmcblk0p2」をマウントするようになったままなので、これを変更しておかないと起動できなくなります。

その前に、Raspbian stretchからディスク指定にPARTUUIDを使うようになったのでHDDのPARTUUIDを確認しておきます。

PARTUUIDは「/dev/disk/by-partuuid/」を「ls -l」すれば分かります。

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

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

今回は「/mnt」を利用しますが、もしそこに何かがあれば他の場所を選択して下さい。

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

でもって、HDD上の/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

ファイル内にあるrootのマウント設定、今回の場合は「PARTUUID=24e66acb-02」を「/dev/sda1のPARTUUID」に書き換えます。

(理論上はUUIDでも指定出来るはずなのですが、私が確認した限りだとUUIDでは上手く行かないみたいです。)

(ちなみに、/dev/sda1と指定したのでも問題なく起動します。複数のディスクを接続する予定がなければその方が簡単かも)

sda1のPARTUUIDは「52a973b2-092f-4ac0-9086-ee7f9cd69795」だったで、それに合わせて書き換えます。

また、/bootの部分は(SDカードが変わってしまうので)PARTUUIDが予測できません。そのため/dev/mmcblk0p1で指定します。(心配であればHDD起動が成功した後にPARTUUIDを調べて書き換えると良いでしょう。)

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

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

別のPCでSDカードのデータをコピー

さて、次はブートローダをコピーしましょう。

まずは、元々刺さっていた(Piで利用していた)SDカードをPCに接続します。

bootパーティションはFAT32なのでWindowsでも認識します。
raspberrypi-usb-boot-006

新しいSDカードにコピーするために、この中にあるファイルを一旦全て別の場所へコピーしておきましょう。

SDカードリーダを複数お持ちでしたらそのまま新しいSDカードにコピーしても構いません。

でもって、コピーしたファイルを新しいSDカードにコピーします。
raspberrypi-usb-boot-007

すなわち、一言で説明すると、「前のSDのデータを新しいSDにコピーする」訳です。

その後、SDカードの中にある「cmdline.txt」をエディタで開きます、notepad.exeでも大丈夫でしたが、サクラエディタとかの方が安全だとは思います。

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

これで出来上がりですね、起動してみて下さい。

起動してみる

きちんと出来ていれば、起動します。

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

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

HDDで動かすのはコツが要ります、慣れるまでは難しいかも……

追:たまに相性の悪いHDDケースがある

この手法で2つのRaspberry Piに使用するHDDを用意し、実際に動かしていました。

ただ、HDDケースに相性があるみたいで、場合によっては認識しない物があります。(4種類用意して2種類で認識せず)

もっと酷いのが、何の前触れもなく、突如としてディスクにアクセス出来なくなる製品があります。(2種類使用して1種類で発生)

ディスクがスリープに入ったっぽい挙動で、再起動すれば動きますけどやはりしばらくすれば死にます。

なので、Pingは通り、ApacheなどのWebサーバにはアクセスできるが404、SSHはログイン出来ず、という状況になりました。

挙動的にディスクからの読み書きが出来ていないみたいで、当然ながらログなんかも残っていません(アクセス出来ないんだからそりゃそうだ)

サーバとして利用する場合は致命的なので、少し様子見をしてから実践投入にした方が良いかもしれません。

何かソフトウェアレベルで解決する方法があるのかも知れませんが、下手に小手先テクニック使うよりは別のHDDケースを用意した方が良いと思います。

という訳で雑な宣伝をねじ込みますが、私は以下のケースを利用しています。

よくよく考えるとケースじゃなくてただの変換ケーブルの方が冷却の面では有利かなぁ、とか思ったり。

もし同じ症状でお困りであればケースとの相性を疑ってみて下さい。

 - コンピューター ,