Raspberry Pi を Fabric と Cuisine を使って自動セットアップする手順を紹介します.
Fabric は Python 製のシンプルなデプロイツールで,シェルスクリプトのような感覚で,リモートで実行する処理を手軽に記述することができます.
一度,Fabric レシピで自動セットアップ出来るようにしておけば,コマンド一発で環境の再構築ができるようになるため,Raspberry Pi を色々といじり倒す際に非常に便利です.
このレシピは,大きく次の 6 つの作業を自動で行います.
- 日本語環境の設定
- SSH 公開鍵のコピー
- 基本的なパッケージのインストール
- 無線 LAN 接続の設定
- SD カード領域全体を有効化
- I2C バスの有効化
2014-12-24 リリースの RASPBIAN で動作確認済です.イメージファイルを SD カードに dd
でコピーした後このレシピを実行するだけで,初期設定が完了します.
では早速使い方について説明していきます.
準備
Fabric と Cuisine のインストール
ホスト側の PC に Fabric と Cuisine をインストールします.Cuisine は Fabric に対して Chef のような抽象度の高い機能を追加するラッパーです.
1 2 3 |
$ sudo apt-get install fabric $ sudo apt-get install python-pip $ sudo pip install cuisine |
無線 LAN の設定ファイルの作成 (任意)
WiFi USBアダプタを使った無線 LAN 接続を行う場合,以下の手順で,wifi_config.py という設定ファイルを作成します.
wpa_supplicant.conf
用の設定値を取得.例えば,接続先のアクセスポイントの SSID を「home_wifi」,パスフレーズを「testtest」とすると,
wpa_passphrase
の実行により下記の出力が得られます.123456$ wpa_passphrase home_wifi testtestnetwork={ssid="home_wifi"#psk="testtest"psk=a90ea4dc2ceea598177ab8cb2b3e47c054259d8b6defc091cc812c0a98822d0e}- wifi_config.py ファイルを作成.
ファイルに,WIFI_SSID と WIFI_PSK の 2 変数を定義します.WIFI_PSK は先ほどのコマンドの出力結果に書かれているものを記載します.
12WIFI_SSID='home_wifi'WIFI_PSK='a90ea4dc2ceea598177ab8cb2b3e47c054259d8b6defc091cc812c0a98822d0e' - 書式チェック.
Python の書式として問題無いかチェックしておきます.エラーが出なければ OK.
1$ python wifi_config.py
Fabric レシピの作成
下記の内容を,fabfile.py
というファイルに保存します.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# -*- coding: utf-8 -*- import imp import os from fabric.api import run, sudo, settings from fabric.decorators import task from fabric.context_managers import hide from fabric.utils import puts import fabric.colors import cuisine @task def setup(): with settings( # hide('warnings', 'stdout', 'stderr') ): # raspi-config の自動起動を無効化 if cuisine.file_exists('/etc/profile.d/raspi-config.sh'): # NOTE: sudo() だと,raspi-config が起動してしまうので run() run('sudo rm -f /etc/profile.d/raspi-config.sh') if os.environ.has_key('RASP_HOSTNAME'): setup_hostname(os.environ['RASP_HOSTNAME']) setup_locale() setup_ssh() setup_package() setup_i2c() setup_wlan() # rootfs サイズを拡張 sudo('raspi-config --expand-rootfs') # 再起動 sudo('reboot') # タイムゾーンとロケールの設定 def setup_locale(): puts(fabric.colors.green('[Setting Locale]', True)) sudo('echo "Asia/Tokyo" > /etc/timezone') sudo('dpkg-reconfigure -f noninteractive tzdata') sudo('sed -i -e \'s/^en_GB.UTF-8 UTF-8/# en_GB.UTF-8 UTF-8/\' /etc/locale.gen') sudo('sed -i -e \'s/^# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/\' /etc/locale.gen') sudo('sed -i -e \'s/^# ja_JP.UTF-8 UTF-8/ja_JP.UTF-8 UTF-8/\' /etc/locale.gen') sudo('dpkg-reconfigure --frontend=noninteractive locales') # タイムゾーンとロケールの設定 def setup_hostname(hostname): puts(fabric.colors.green('[Setting Hostname]', True)) sudo('sed -i -e \'s/^.*/%s/\' /etc/hostname' % (hostname)) sudo('sed -i -e \'s/^127.0.1.1\t.*/127.0.1.1\t%s/\' /etc/hosts' % (hostname)) # 公開鍵のコピー def setup_ssh(): puts(fabric.colors.green('[Install SSH Publickey]', True)) with cuisine.mode_sudo(): cuisine.ssh_authorize("pi", cuisine.file_local_read('~/.ssh/id_rsa.pub')) # パッケージのインストール def setup_package(): puts(fabric.colors.green('[Install Packages]', True)) with cuisine.mode_sudo(): cuisine.package_update() cuisine.package_upgrade() cuisine.package_ensure([ 'gcc', 'make', 'automake', 'emacs23-nox', 'tmux', 'ruby', 'git', 'zsh', 'mlocate', ]) # I2C の有効化 def setup_i2c(): sudo('sed -i -e \'s/^blacklist i2c-bcm2708/# blacklist i2c-bcm2708/g\' ' + '/etc/modprobe.d/raspi-blacklist.conf') # WiFi の有効化 def setup_wlan(): if not cuisine.file_exists('/sys/class/net/wlan0'): return puts(fabric.colors.green('[Setting Wireless LAN]', True)) wifi_config = None try: (file, pathname, description) = imp.find_module('wifi_config', ['.']) wifi_config = imp.load_module("wifi_config", file, pathname, description) except ImportError: puts(fabric.colors.red('SKIP WiFi Configuration. (FAILED to load wifi_config.py)', True)) return cuisine.file_write( location = '/etc/wpa_supplicant/wpa_supplicant.conf', content = 'ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev\n' + 'update_config=1\n' + 'network={\n' + (' ssid=\"%s\"\n' % (wifi_config.WIFI_SSID)) + (' psk=%s\n' % (wifi_config.WIFI_PSK)) + ' key_mgmt=WPA-PSK\n' + ' proto=WPA2\n' + ' pairwise=CCMP\n' + ' group=CCMP\n' + '}\n', mode='600', sudo=True ) sudo('sed -i -e \'s/^wpa-roam \/etc\/wpa_supplicant\/wpa_supplicant.conf/' + 'wpa-conf \/etc\/wpa_supplicant\/wpa_supplicant.conf/\' /etc/network/interfaces') sudo('sed -i -e \'s/^iface wlan0 inet manual/iface wlan0 inet dhcp/\' /etc/network/interfaces') # NOTE: Wifi の場合は「ホスト名-wifi」でアクセスできるようにする dhclient_conf = cuisine.text_ensure_line( cuisine.file_read('/etc/dhcp/dhclient.conf'), 'interface "wlan0" { send host-name = concat (gethostname(), "-wifi"); }' ) cuisine.file_write( location = '/etc/dhcp/dhclient.conf', content = dhclient_conf, mode='644', sudo=True ) # Local Variables: # coding: utf-8-unix # mode: python # c-basic-offset: 4 # tab-width: 4 # indent-tabs-mode: nil # End: |
セットアップの実行
Raspberry Pi を LAN 接続した状態で下記のコマンドを実行します.「raspberrypi」というホスト名でアクセス出来ない場合は,「pi@192.168.0.100」のような感じで IP アドレス指定します.パスワードを聞かれますので,「raspberry」を入力して ENTER を押すと,自動的にセットアップが始まります.
1 |
$ fab -a -H pi@raspberrypi setup |
数分間かけてセットアップ処理を行った後,Raspberry Pi は自動的に再起動します.
環境の設定と同時にホスト名の変更を行いたい場合は,環境変数 RASP_HOSTNAME にホスト名を指定して実行します.
1 |
$ env RASP_HOSTNAME=新しいホスト名 fab -a -H pi@raspberrypi setup |
備考
上に掲載した Fabric レシピは冪等性がありますので,同じホストに対して複数回実行しても問題ありません.
「-a」オプションは,SSH のパスワード認証をするためのものなので,レシピによって SSH の公開鍵を配置したあとは不要となります.
コメント
[…] Fabric とCuisine による Raspberry Pi の自動セットアップhttps://rabbit-note.com/2014/12/31/fabric-cuisine-raspberry-pi-automated-setup/ […]