純規の暇人趣味ブログ

手を突っ込んで足を洗う

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

      2016/08/08    HimaJyun

どうもこんにちは、Raspberry Piを利用したサーバ作りで絶賛大忙しのマイクラ鯖缶@HimaJyunです。(HimaJyunなのに忙しい)

サーバで利用するとなると漏れなく24時間動かす訳ですが、それにSDカードを利用するのは不安要素があり過ぎです。
ですので、今回はRaspberry PiをUSBで起動する様に(要はOSをUSB接続のHDDに置けるように)してみようと思います。

用意した物

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

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

USB(HDD)

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

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

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

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

SDカード

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

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

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

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

HDDで起動しよう

ざっと説明すると「1.ddでデータをコピー」「2.ディスクの調整」「3.別のPCでSDカードのデータをコピー」の3ステップです。

ddでデータをコピー

まず最初に、HDDを接続してからRaspberry Piを起動した方が確実です。

起動したらログインして「sudo fdisk -l」を実行します、コマンドの結果は以下のようになるはずです(一部端折ってます)

pi@raspberrypi:~ $ sudo fdisk -l
Disklabel type: dos
Disk identifier: 0xc8b81e22

Device Boot Start End Sectors Size Id Type
/dev/mmcblk0p1 8192 137215 129024 63M c W95 FAT32 (LBA)
/dev/mmcblk0p2 137216 31422463 31285248 14.9G 83 Linux

The backup GPT table is corrupt, but the primary appears OK, so that will be used.

Disk /dev/sda: 1.8 TiB, 2000398934016 bytes, 3907029168 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: 649DF7E6-34C1-4920-A9DA-78B35D9A4B6D

Device Start End Sectors Size Type
/dev/sda1 2048 3907028991 3907026944 1.8T Microsoft basic data

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

「/dev/sda1」がHDDの第一パーティションですね、場合によってはsda2,sda3...とあるかも知れません。

もし、パーティション分けが必要であればここでパーティション分けを行って下さい。
今回はディスク全体を使うのでこのままddします。

今回の場合だと「sudo dd if=/dev/mmcblk0p2 of=/dev/sda1 bs=32M conv=noerror,sync」ですね。
ここでifとofを間違えるとSDカード上のデータが全て消えるので全神経を研ぎ澄まして実行して下さい、ifのiはInput(入力)のi、ofのoはOutput(出力)のoですよ。

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

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

ディスクを調整する

このまま使えれば幾分か楽なんですけどね、世の中そう甘くないです。
パーティション周りの操作を行ったので、まずはディスクのチェックを行いましょう。

ディスクのチェックは「sudo 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回やっても9999回やっても「Fix<y>? 」と聞いて来るならきっとそのディスクは逝ってます。

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

これではいみねーですわなのでパーティションを拡張します「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.

拡張が終わったらもう一度チェック(e2fsck)しておくことをお勧めしますよ。

でもって、書き込みが終わったHDD上の/etc/fstabを編集する必要があります。
今のままではrootとして「/dev/mmcblk0p2」をマウントする様になったままなので、これを変更しておかないと起動できなくなります。

まずは、適当な場所にHDDをマウントしましょう。
今回は「/mnt」を利用しますが、もしそこに何かがあれば他の場所を選択して下さい。

pi@raspberrypi:~ $ sudo mount -t ext4 -o defaults /dev/sda1 /mnt

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

ファイル内にあるrootのマウント設定(と言ったらいいのかな?)、今回の場合は「/dev/mmcblk0p2」を「/dev/sda1」に書き換えます。
raspberrypi-usb-boot-004raspberrypi-usb-boot-005

これで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(今回の場合だと/dev/mmcblk0p2)を指定している部分があるので、それを新しいHDD上のroot(/dev/sda1)に書き換えます。
raspberrypi-usb-boot-008raspberrypi-usb-boot-009

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

起動してみる

きちんと出来ていれば、起動します。
もし起動出来ない場合はディスプレイを接続すると起動処理の際にエラーが出てくれるので原因が分かりやすいです。

失敗したのならもう一度最初からやり直してみましょう、大丈夫です、大切な彼女の大事な写真はSDカードの方にきちんと残っています。
出来るまでやり直すのです、思い込みが失敗の原因である事はしょっちゅうです。

ちなみにですが、この作業を繰り返し複数台のHDDに対して行う事で、全く同じデータを持ったHDDが複数出来上がります。(その場合は先にSDカード内の/etc/fstabを書き換えておいた方が楽です、後で忘れずに戻しておきましょうね。)

すなわち、同じ設定のラズパイを大量に用意して並列処理(Webサーバのロードバランシングとか)の下ごしらえが出来ます。
(ローカルIPアドレスを固定にしている場合は変更するのを忘れずに)

僕はラズパイが2つあるのでセットアップを済ませたSDカードをこれで2つのHDDにコピーする予定です。

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

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

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

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

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

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

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

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

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

僕はこれで2日潰れたので死んだ鯖の目をしながら電気屋に新しいHDDケースを買いに走りました、ザ・宣伝臭がしますが、以下の製品であれば(少なくとも僕の手元にあるRaspberry Piでは)正常に動作します。(ファンも一応付いていますし)

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

 - パソコン ,