Raspberry Pi OSインストールから初期設定まで 2022 年版
Raspberry Pi 3インストールから初期設定まで - johshisha’s diary
の情報が古くなってちょくちょく追記してきたのですが、いよいよ管理不能になってきたので、別記事を作りました。 主に自分用のメモですが、他の人のお役に立てれば幸いです。
Raspberry Pi OS のインストール
raspberry-pi-imager を使うと SD へのインストール周りはかなり簡単にできました
raspberry-pi-imager のインストールは以下のコマンドから。 操作方法は割と直感的だったので省きます。(もしわからなければ別途調べてください)
$ brew install --cask raspberry-pi-imager
ネットワークエラーになる場合は Operating system images – Raspberry Pi からダウンロードしてきて、スタンドアロンモードで書き込みをするとよい。
SSH, Wifi の設定
/boot/
以下に下に示すファイル名でファイルを置いておくと、起動時にいい感じに設定してくれる。
wpa_supplicant.conf
country=JP ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="{Wi-FiのSSID}" psk="{Wi-Fiのパスワード}" scan_ssid=1 }
ssh
空ファイルを置けばよい
$ touch /Volumes/boot/ssh
SSH 接続
SDを挿して電源をつなげばSSHできる状態で起動しているはず。 初期ユーザは以下。
username: pi password: raspberry
raspberrypi.local
というローカルドメインが設定されているみたいなので、それを利用すると IP アドレスなどを調べる手間もかからない。
ssh pi@raspberrypi.local
こまごました初期設定
update
$ sudo apt-get update && sudo apt-get upgrade -y
Timezone の設定
$ sudo timedatectl set-timezone Asia/Tokyo
IP アドレスの固定化
ローカルドメインが割り振られているので必要ない場合は飛ばして良い
$ sudo vim /etc/dhcpcd.conf
以下の設定を追記
interface wlan0 static ip_address=192.168.11.xx static routers=192.168.11.yy static domain_name_servers=192.168.11.yy
SSH Port 変更
$ sudo vim /etc/ssh/sshd_config
ユーザーの追加削除
ユーザ(hoge)の追加
$ sudo adduser hoge $ sudo gpasswd -a hoge sudo
piユーザの削除
$ sudo userdel pi
自動ログイン解除
GUIありのOSの場合、自動で pi ユーザーにログインがされてしまいユーザーの削除ができなかった。 ので、自動でログインをしないようにする。
sudo vim /etc/lightdm/lightdm.conf
autologin-user=pi
の部分を削除する or コメントアウトする
これでうまくいかない場合は raspi-config
からの設定も必要 (Boot Options)
公開鍵認証
パスワードでなく公開鍵認証でログインできるようにします。 ローカルのマシンで以下のように鍵を生成しRaspberry piに送信します。
$ ssh-keygen -t ed25519 $ scp -P [port_number] ~/.ssh/id_ed25519.pub [username]@[ip]: $ ssh -P [port_number] [username]@[ip]
raspberrypi側で,送られてきた鍵を登録します.
$ mkdir .ssh $ mv ~/id_ed25519.pub ~/.ssh/authorized_keys $ chmod 600 ~/.ssh/authorized_keys $ sudo service ssh restart
パスワードログインの無効化
$ sudo vim /etc/ssh/sshd_config
PasswordAuthentication no
firewall
無駄なportにはアクセスできないようにする。
$ sudo apt-get install ufw -y $ sudo ufw default deny $ sudo ufw allow 80/tcp $ sudo ufw allow [ssh port_number] # SSH用のポートは開けておく $ sudo ufw enable
ローカルマシンの設定
ssh configの設定
~/.ssh/config
に以下を追記。
Host raspberry Hostname [ip] Port [port_number] User [username] IdentityFile ~/.ssh/id_ed25519
Install packages
anyenv
yarn
chainerでモデルを入れ子にしたら重みが更新されなかった話
概要
chainerのmodel(Chainクラス)を入れ子にして使っていたら重みが更新されなかった.
Chainクラスで重みの更新がされるのは self.init_scope()
内に書いている link
オブジェクトだけだったことが判明し,
with self.init_scope():
以下に書くとちゃんと更新された.
状況
version
chainer==3.0.0
やりたかったこと
あるmodelA
に layerN
を追加して,新たに modelB
を作成したかった.
だめなコード
計算グラフを出力すると,ちゃんとmodelA -> layerN という風に接続されていたので,これでうまく接続されているものだと思っていた.
が,実際に学習中に都度重みを出力してみると,modelA内の重み(l1, l2, l3の重み)が全く更新されていないことがわかった.
# example/train_mnist.pyから拝借 class modelA(chainer.Chain): def __init__(self, n_units, n_out): super(modelA, self).__init__() with self.init_scope(): self.l1 = L.Linear(None, n_units) # n_in -> n_units self.l2 = L.Linear(None, n_units) # n_units -> n_units self.l3 = L.Linear(None, n_out) # n_units -> n_out def __call__(self, x): h1 = F.relu(self.l1(x)) h2 = F.relu(self.l2(h1)) return self.l3(h2) class modelB(chainer.Chain): def __init__(self, n_out, modelA): super(modelB, self).__init__() self.modelA = modelA with self.init_scope(): self.layerN = L.Linear(None, n_out) def __call__(self, x): h1 = F.relu(self.modelA(x)) h2 = self.layerN(h1) return h2
よいコード
まあちゃんとドキュメント見ればそれっぽいことは書いてあるんだが,まったく気づかなかった..
init_scope内に書くと,context managerとやらに登録されるらしい.
chainer.Chain — Chainer 3.0.0 documentation
# example/train_mnist.pyから拝借 class modelA(chainer.Chain): def __init__(self, n_units, n_out): super(modelA, self).__init__() with self.init_scope(): self.l1 = L.Linear(None, n_units) # n_in -> n_units self.l2 = L.Linear(None, n_units) # n_units -> n_units self.l3 = L.Linear(None, n_out) # n_units -> n_out def __call__(self, x): h1 = F.relu(self.l1(x)) h2 = F.relu(self.l2(h1)) return self.l3(h2) class modelB(chainer.Chain): def __init__(self, n_out, modelA): super(modelB, self).__init__() # self.modelA = modelA with self.init_scope(): self.modelA = modelA # ここに書くのが正解 self.layerN = L.Linear(None, n_out) def __call__(self, x): h1 = F.relu(self.modelA(x)) h2 = self.layerN(h1) return h2
まとめ
重み更新したい link
オブジェクトは init_scope
内に書きましょう.
逆に,fine-tuningとかで重みを更新したくない場合は, init_scope
内に書かなければ更新されないようなので,便利だなーと思った.
ドキュメントはちゃんと読みましょう.
機械学習など時間のかかる処理をするときに便利なBotを作成した
3行
作ったもの
README
なんだこれ
お知らせ蜂bot
slackに任意のコマンドの終了を可愛くお知らせしてくれるので通知の度に幸せになれる
Successのときは緑,Errorのときは赤で,わかりやすく表示してくれる親切さ. 機械学習等の実行に時間のかかるプログラムを実行するときに利用するつもりで作成した
セットアップ
$ git clone https://github.com/johshisha/bee $ cd bee $ chmod 777 bee.sh $ echo "alias bee=\"`pwd`/bee.sh\"" >> ~/.zshrc $ source ~/.zshrc
bee.sh内の以下の設定を自分の好きなように変える
WEBHOOKURL="WebhockのURL入れてね" #slack 送信チャンネル CHANNEL=${CHANNEL:-"#general"} #メッセージ WEBMESSAGE="Command: ${COMMAND}\nStart time: ${start}\nEnd time: ${end}" #メンションするユーザ MENTION_USER="@channel"
使い方
$ bee $COMMAND
COMMANDは任意のコマンド
e.g.,
$ bee python train.py --epoch 50
研究で使うGPU環境をサクッと使えるDocker Imageを作った
研究を進めるにあたって便利だと感じたのでDocker環境下で実験をすることにした.
その際に作成した,Docker環境を公開します.
3行
- DeepLearningに必要なGPUの環境を構築済みのDocker Imageを作成した
- docker pullしてくるだけでGPU環境を作れる(nvidia-dockerさえあれば)
- 研究の引き継ぎ&公開をうまくやろう!
作ったもの
メリット
Dockerを利用して研究を進めるメリットは以下の2点
- ゼロからGPU環境を作るのが楽になる
- 研究成果の引き継ぎ&公開が簡単
ゼロからGPU環境を作るのが楽になる
私は初めてGPU環境を構築したときに,かなり苦戦して,数日戦ったことがある.
また,なぜか起動しなくなったことがあり,再インストールする機会が何度かあり,毎度苦戦していた.(そのおかげで今はなんとかなるようにはなったが...)
Dockerを利用することで,いくつかのコマンドを叩くだけで,簡単にGPU環境が構築できるので,もう辛い思いはしなくていい!
研究成果の引き継ぎ&公開が簡単
研究を引き継ぐ際に,PCごと引き継げは簡単なのだが,実際はそうはいかず,スクリプトだけ引き継ぐことが多いと思う.
その際に問題になるのが,環境の問題で実行できないことである.
(例えばMecabやopencv,GPU環境のセットアップができていないなど)
そこで,Dockerを使うことで,環境の差異による実行できない問題は解決され,引き継ぎが楽になる!
さらに,研究成果を公開する際に,最近はgithub repositoryも一緒に論文に載せることが多いと思うが,Dockerfileを添えてあげるだけで,再現実験の環境が一発で整うので,再現実験のハードルが下がり,citation数の増加にも繋がる!!というお得しかない状況が発生する(かもしれない).
ということで
研究はDocker環境下でやることが個人的におすすめなので,ぜひ今回作成したツールを使って,快適な研究生活を送っていただけると幸いです!!
まだ,作って間もないので,不具合等あればご一報いただけると幸いです.
使い方
Dockerfileを作って,自分の環境用にbuildするとGPU環境が出来上がる.
例:サンプルのDockerfileを用意した
$ wget https://raw.githubusercontent.com/johshisha/docker_for_research/master/sample/Dockerfile # Dockerfileのサンプルを取ってくる $ touch requirements.txt # 必要なら編集して自分の必要なライブラリを書く $ docker build -t sample/sample . # 自分用の名前をつけてbuildする $ nvidia-docker run --rm -it -p 8888:8888 -v "$PWD":/home/docker/work sample/sample jupyter-notebook --ip=0.0.0.0 # docker内のjupyter-notebookを起動 # `http://0.0.0.0:8888/?token=~~~`にアクセス
ちなみにDocker Imageに以下のライブラリはデフォルトでインストールしてあります.
cupy pandas jupyter matplotlib keras tensorflow-gpu chainer sklearn
使う前の準備
使う際には,以下のインストールが必要です.
- docker
- nvidia-docker
インストール方法
(動作の検証はubuntu16.04でしましたが,クリーンインストールはしていないので,多少違いがあるかもしれないです..)
- dockerのインストール
dockerのインストールは簡単です
$ sudo su root# curl -fsSL https://get.docker.com/ | sh root# gpasswd -a [username] docker root# exit -- logout user $ docker run hello-world # 動作確認
- nvidia-dockerのインストール
これは地味に詰まりました(環境によって少し違うかもしれません)
$ wget -P ./tmp https://github.com/NVIDIA/nvidia-docker/releases/download/v1.0.1/nvidia-docker_1.0.1-1_amd64.deb $ sudo dpkg -i ./tmp/nvidia-docker*.deb && rm -f ./tmp/nvidia-docker*.deb $ nvidia-docker run --rm nvidia/cuda:8.0 nvidia-smi # 動作確認
↑基本はこれだけ
でも私の環境ではいろいろとエラーがでました
- Error1: libcuda.soのファイルが既にある
$ nvidia-docker run --rm nvidia/cuda:8.0 nvidia-smi docker: Error response from daemon: create nvidia_driver_375.82: VolumeDriver.Create: internal error, check logs for details. See 'docker run --help’. $ systemctl status nvidia-docker … Error: link /usr/local/cuda-8.0/targets/x86_64-linux/lib/stubs/libcuda.so /var/lib/nvidia-docker/volumes/nvidia_driver/375.82/lib64/libcuda.so: file exists
$ sudo mv /usr/local/cuda-8.0/lib64/stubs/libcuda.so /usr/local/cuda-8.0/lib64/stubs/libcuda.so.backup $ nvidia-docker run --rm nvidia/cuda:8.0 nvidia-smi Tue Oct 17 11:44:46 2017 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 375.82 Driver Version: 375.82 | |-------------------------------+----------------------+———————————+ …
- Error2: nvidia-modprobeがインストールされてないんじゃない?
$ nvidia-docker run --rm nvidia/cuda:8.1 nvidia-smi ... Error: Could not load UVM kernel module. Is nvidia-modprobe installed?
$ sudo apt-get install nvidia-modprobe $ nvidia-docker run --rm nvidia/cuda:8.0 nvidia-smi Tue Oct 17 11:44:46 2017 +-----------------------------------------------------------------------------+ | NVIDIA-SMI 375.82 Driver Version: 375.82 | |-------------------------------+----------------------+———————————+ …
まとめ
研究はDocker環境下でやるとみんな幸せになれる!(はず)
最低限のjavascript開発環境を作って公開した
三行
- yarn, gulp, babel, webpack, React, ESlintを使って,最低限のjavascript開発環境を作った
- 最低限 = ES6で書いたものがコンパイルされてブラウザで見れる状態
- 最適な環境なのかはわからないが,とりあえず開発できる
作ったもの
使い方
$ git clone https://github.com/johshisha/js_development $ cd js_development $ yarn $ yarn start $ open http://localhost:8080/webpack-dev-server/index.html
buildの仕方
$ yarn start build
参考文献
基本的にこれを参考にさせてもらった
これの8章までに webpack-dev-server を加えた形
qiita.com
webpack-dev-server
dackdive.hateblo.jp
補助:
Webpack-stream WITH Gulp WITH webpack-dev-server?? · Issue #121 · shama/webpack-stream · GitHub
usage with gulp
HMR
詰まった点
Hot Module Replacement (HMR)がうまく動作しない
webpack-dev-serverでHMRをしようとおもい, hot: true
にしたが,うまく動作しなかった
HMR: リロードせずとも,変更のあった部分だけ更新してくれる機能
原因
設定が正しく出来ていなかった解決法
github.com
それでもHot Module Replacement (HMR)がうまく動作しない
こういう変更をリロード無しで更新してくれることを期待していた
Before
const App = () => ( <div> Hello world! </div> );
After
const App = () => ( <div> Hello world!!!!!!!!!!!!!!!!! </div> );
原因
HMRを万能なものと思いすぎていた
すべての変更に対応しているわけではなく,HMRに対応している変更としていない変更がある解決法
ファイルを分割してReact ComponentにすることでComponent内の変更はHMRに対応することができた
このあたりの仕組みまでは理解できていないので,理解する必要がある.
↓こんな感じに分割した https://github.com/johshisha/js_development/blob/master/src/client/Message.jsx
class Message extends Component { render() { return ( <div> Hello world! </div> ); } }
コンポーネントとか期待してたのに, undefined
が返ってきてるじゃん!というエラー
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in.
原因
importの仕方を間違っていた解決法
- import { Message } from './Message'; + import Message from './Message';
RaspberryPiにDocker環境を整える[docker+docker-compose]
参考資料 blog.hisurga.com
この資料にそってやるのがいいかと
一応コマンドだけ残しておく(同じことしている)
dockerのインストール
$ curl -sSL https://get.docker.com | sh $ sudo usermod -aG docker [username] # root以外でもdocker使えるようにする
一旦ログアウトする
動作確認
$ docker run -d -p 80:80 hypriot/rpi-busybox-httpd
clientから,ブラウザでraspberry piのIPにアクセスすると画像が表示されればOK
docker-composeのインストール
なぜかエラーが出た..
が,docker rmi
してからやり直すといけた
$ git clone https://github.com/docker/compose.git $ cd compose $ sed -i -e 's/^FROM debian\:/FROM armhf\/debian:/' Dockerfile.armhf $ sed -i -e 's/x86_64/armel/g' Dockerfile.armhf $ docker build -t docker-compose:armhf -f Dockerfile.armhf . # めっちゃ時間かかる $ docker run --rm --entrypoint="script/build/linux-entrypoint" -v $(pwd)/dist:/code/dist -v $(pwd)/.git:/code/.git "docker-compose:armhf" $ ls -l dist/ $ sudo cp dist/docker-compose-Linux-armv7l /usr/local/bin/docker-compose $ sudo chown root:root /usr/local/bin/docker-compose $ sudo chmod 0755 /usr/local/bin/docker-compose
動作確認
$ docker-compose version
Raspberry Pi 3インストールから初期設定まで
インストール
今回は,2017-04-10-raspbian-jessie-lite.img
を使用しました.
各自公式からダウンロードしてきてください.
(追記) raspberry-pi-imager を使うと SD へのインストール周りはかなり簡単にできました
raspberry-pi-imager のインストールは以下のコマンドから。 操作方法は割と直感的だったので省きます。(もしわからなければ別途調べてください)
$ brew install --cask raspberry-pi-imager
該当SDの確認
$ diskutil list ... /dev/disk4 (internal, physical): #: TYPE NAME SIZE IDENTIFIER 0: FDisk_partition_scheme *31.0 GB disk4 1: DOS_FAT_32 RASPBIAN 31.0 GB disk4s1
該当のSDを見つけます.
SDのフォーマット
$ diskutil eraseDisk MS-DOS RASPBIAN /dev/disk4 ... Finished erase on disk4
RASPBIAN
の部分はフォーマット後の名前なのでお好みで設定してください
SDへ書き込み
以下のコマンドを実行し,SDに書き込む.(10分ほど?適当に放置して待ちましょう)
$ diskutil unmountDisk /dev/disk4 $ sudo dd if=path/to/file/2017-04-10-raspbian-jessie-lite.img of=/dev/disk4 bs=1m
以上を行うと準備は完了なので,RaspberryPiに挿入して電源を入れましょう 最初はWifi等の設定を行うまでネットに接続できないので,LANケーブルを挿しました.
初期設定
初期のパスワード
user name: pi password: raspberry
rootのパスワード設定
sudo passwd root
以下からはrootで行う
$ su - password
Update
とりあえず最新にします
$ apt-get update && apt-get upgrade $ apt-get install vim # 後々の設定ファイル編集のために入れておく
E: Broken packages
と言われて失敗するとき ↓
update / upgrade fails on older Raspian Installation - Raspberry Pi Forums
sudo apt full-upgrade sudo apt dist-upgrade
Wifiの接続
SSIDとパスワードを設定ファイルに保存しておきます. このファイルはパスワードが記載されているので,外部に公開しないようにしましょう.
$ export PASSWORD=password $ export SSID=wifi-ssid $ wpa_passphrase $SSID $PASSWORD >> /etc/wpa_supplicant/wpa_supplicant.conf
(追記)
/boot/
以下に wpa_supplicant.conf というファイルをおいておけば起動時にいい感じにしてくれる
country=JP ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev update_config=1 network={ ssid="{Wi-FiのSSID}" psk="{Wi-Fiのパスワード}" scan_ssid=1 }
Time Zoneの設定
とりあえず日本時間に変更します.
$ raspi-config
「4 Localisation Options」-> 「I2 Change Timezone」->「Asia」-> 「Tokyo」
or
$ sudo timedatectl set-timezone Asia/Tokyo
SSHの有効化
デフォルトではSSHで接続できないので,設定をONにします.
$ raspi-config
「5 Interfacing Options」-> 「P2 SSH」->「Yes」
(追記)
/boot/
以下に ssh
という空ファイルをおいておけば起動時にいい感じに ssh を有効化してくれる
接続先IPは以下で確認
$ ip route default via 192.168.1.1 dev wlan0 metric 303 192.168.1.0/24 dev wlan0 proto kernel scope link src 192.168.1.42 metric 303
今回の場合は192.168.1.42となります.
$ ssh pi@192.168.1.42
で接続できるはずです
おまけの設定
RaspberryのIPを固定する
上記の設定で,SSHすることができましたが,このままだとRaspberry piを再起動した際に,IPが変わってしまいSSHできなくなる可能性があります. そのたびにディスプレイを挿して,IPを確認して...という作業はめんどうなので,IPを固定化します.
上記の例では,サブネットマスクが,192.168.1.0/24
なので,左から24bit分の192.168.1
までがネットワークアドレスであり,これ以降の8bitは好きに使用して良いことがわかります.
好きに設定はできますが,特にこだわりがなければ,とりあえず今のIP( 192.168.1.42
)で固定すればよいかと思います.
以下のファイルを編集し,設定を追記していきます.
$ sudo vim /etc/dhcpcd.conf
以下の設定を追記
interface wlan0 static ip_address=192.168.1.42 static routers=192.168.1.1 static domain_name_servers=192.168.1.1
これで固定化できました. 再起動してもIPが変わらないことを確認してください.
SSHのポート変更
22番のままだと悪意のあるユーザに推測されやすいためセキュリティの面で不安があります.
変更する際は,/etc/ssh/sshd_config
のPort 22を変更するとSSHの接続Portを変更できます.
ユーザの追加と削除
デフォルトのpi
ユーザ名はすべてのRaspberry piで共通なので,悪意のあるユーザに推測されやすいです.(パスワードも共通なので,変更する必要があります)
外部からアクセスできるようにする際は,ユーザを新たに作り直して,攻撃されにくくしておくとよいです.
ユーザ(hoge)の追加
$ sudo adduser hoge $ sudo gpasswd -a hoge sudo
piユーザの削除
$ sudo userdel pi
公開鍵認証
パスワードでなく,公開鍵認証でログインできるようにします. ローカルのマシンで.以下のように,鍵を生成しRaspberry piに送信します.
$ ssh-keygen -t rsa $ scp -P [port_number] ~/.ssh/id_rsa.pub [username]@[ip]: $ ssh -P [port_number] [username]@[ip]
raspberrypi側で,送られてきた鍵を登録します.
$ mkdir .ssh $ mv ~/id_rsa.pub ~/.ssh/authorized_keys $ chmod 600 ~/.ssh/authorized_keys $ sudo service ssh restart
ローカルのマシンの別ターミナルで確認します.
$ ssh -p [port_number] -i ~/.ssh/id_rsa [username]@[ip]
うまくsshできることが確認できたら成功です.
公開鍵認証でログインできるようになったので,パスワードでログインできないようにして,セキュリティを高めます. raspberry側で,設定ファイルを以下のように変更します.
$ sudo vim /etc/ssh/sshd_config
-
の部分を +
になるように書き換えます.
- # PasswordAuthentication no + PasswordAuthentication no
ssh configの設定
SSHする際に,ipなど,入力するコマンドが長くて面倒なのでSSHコマンドを簡略化します.
ローカルのマシンで,~/.ssh/config
に以下を追記.
Host raspberry Hostname [ip] Port [port_number] User [username] IdentityFile ~/.ssh/id_rsa
これを記載することで,sshを簡略化することができます.
$ ssh -p [port_number] -i ~/.ssh/id_rsa [username]@[ip] # 通常はこれ $ ssh raspberry # configを設定することで簡略化できる
firewall
セキュリティを高めるために,無駄なportにはアクセスできないようにしておきます.
$ sudo apt-get install ufw -y $ sudo ufw default deny $ sudo ufw allow 80/tcp $ sudo ufw allow [ssh port_number] # SSH用のポートは開けておく $ sudo ufw enable
自動ログイン解除
sudo vim /etc/lightdm/lightdm.conf
autologin-user=pi
の部分を削除する or コメントアウトする
これでうまくいかない場合は raspi-config
からの設定も必要 (Boot Options)