読者です 読者をやめる 読者になる 読者になる

Raspberry Pi 3の起動時に自動無線LAN接続(2)

前回の続きです!
前回:Raspberry Pi 3の起動時に自動無線LAN接続(1) - usmysaの開発メモ

前回、コマンドから無線LANに繋ぐ方法を紹介しました。
今回は、シェルスクリプトを使って、それを自動化するスクリプトを作成したいと思います。

シェルスクリプトとは

シェルスクリプトとは、複数の処理をまとめて行う(バッチ処理)ときに使われる、OSのシェルが直接解釈・処理できるスクリプト

引用:シェルスクリプトとは|shell script - 意味/定義 : IT用語辞典


そもそもスクリプトとは…

コンピュータプログラムの種類の一つで、機械語への変換や実行可能ファイルの作成などの過程を省略または自動化し、ソースコードを記述したら即座に実行できるようなプログラムのことをスクリプトという。

引用:スクリプトとは|script|scr - 意味/定義 : IT用語辞典

なるほど。
スクリプトとは、コンパイルが必要ない言語のことを言うんですね。
スクリプト言語の例としては、PythonRubyなどがあります。
つまり、シェルスクリプトとは、シェルのスクリプト(=コンパイルが必要ないプログラム)ってことですね!

起動時に自動で接続するための手順


f:id:usmysa:20160520171816p:plain


サーバ起動時に実行するコマンドとして、「chkconfig」があります。
これに作成したスクリプトを登録して、ラズパイが起動したときに実行させます。

いざ、スクリプトを書いてみる

スクリプト名は、「wifi-connect-script」となっています。
コードは以下のとおりです。

# !/bin/sh
# chkconfig: 2345 99 20
# description: wifi-connect-script

LoopConnectWiFi(){
  ssid=$1
  password=$2
  nmcli d wifi connect ${ssid} password ${password}
  result_connect='nmcli d wifi connect $ssid password $password'
  success_str="Device 'wlan0' successfully activated with"
  if [ ! 'echo ${result_connect} | grep ${success_str}' ]; then
    sleep 3
    LoopConnectionWiFi $ssid $password
  fi
}

readonly ssid_array=($(nmcli d wifi))
readonly wifi="SSID"
readonly wifi_pass="SSIDのパスワード"

case "$1" in
  start)
    for ssid in "${ssid_array[@]}"; do
      if [ $ssid = $wifi ]; then
        LoopConnectWiFi $wifi $wifi_pass
      fi
    done
    ;;
  stop)
    ;;
  *)
    ;;
esac

解説

# !/bin/sh

まず、これを書くことで、「このテキストはシェルスクリプトである」ということを宣言します。
なので、シェルスクリプトを書く場合は絶対必要な部分となります。

# chkconfig: 2345 99 20
# description: wifi-connect-script

これは、chkconfigの設定を記述しています。

2345 起動させるランレベル ランレベルを数字で入力。複数ある場合は、連続して2345のように各。- と書くと全てのランレベルでOFFとする。
99 起動時の優先度 数値(1~99までで記入するのが一般的)で記入。数字が大きくなるほど後で起動される。
20 停止時の優先度 数値(1~99までで記入するのが一般的)で記入。数字が大きくなるほど後で停止される。

ランレベルとは、Linux OSの動作モードを表します。

0:システムの停止
1:シングルユーザーモード、ネットワーク無し
2:マルチユーザーモードNFSマウントなし)
3:マルチユーザーモード(コンソール)、ネットワーク有り
4:未使用
5:マルチユーザーモードX Windows)、ネットワーク有り
6:システム再起動

引用:ランレベルとは(chkconfig) - Linux入門 - Webkaru

「description」はサービスの説明です。
適当に書いといて大丈夫です。

readonly ssid_array=($(nmcli d wifi))
readonly wifi="SSID"
readonly wifi_pass="SSIDのパスワード"

「nmcli d wifi」はWiFiの一覧を表示するコマンドで、その結果を「ssid_array」という配列に代入しています。
また、ここら辺の変数は書き換えることはないと思うので、一応「readonly」にして読み込み専用にしています。

case "$1" in
  start)
    for ssid in "${ssid_array[@]}"; do
      if [ $ssid = $wifi ]; then
        LoopConnectWiFi $wifi $wifi_pass
      fi
    done
    ;;
  stop)
    ;;
  *)
    ;;
esac

この部分は、switch文になってます。
「$1」っていうのは、シェルスクリプトでは第1引数を表します。
ここは覚えとく必要があります。
で、for文を使ってWiFi一覧の中から接続したいWiFiがあったら、LoopConnectWiFiメソッドを呼び出すという仕組みになっています。
この時、switch文で「start」の場合しか使ってないので、if文で書いた方が正しいのかなと思います。

nmcli d wifi connect ${ssid} password ${password}

前回で紹介しましたが、これでWiFiに接続しています。

result_connect='nmcli d wifi connect $ssid password $password'
success_str="Device 'wlan0' successfully activated with"
if [ ! 'echo ${result_connect} | grep ${success_str}' ]; then
  sleep 3
  LoopConnectionWiFi $ssid $password
fi

「result_connect」には、WiFiに接続した後に表示される文章を代入しています。
そして、result_connectが失敗していた場合、3秒ごとに再接続するような仕組みになっています。

chkconfigに登録する

$ sudo mv wifi-connect-script /etc/init.d/
$ sudo chkconfig --add wifi-connect-script
$ sudo chkconfig wifi-connect-script on


これで、Raspberry Pi 3が起動した時に自動で無線LANに接続します!
個人的に、ソースコードにパスワードを書くのは非常に嫌いなんですが、良い方法を知っている方がいれば教えて下さい!

参考:bash: コマンドの実行結果を配列や変数に代入する | deadwood
   (CentOS6まで)自作のサービスをchkconfigで登録する
   シェルスクリプトで関数を利用する - Qiita
   文字列Aに文字列Bが含まれるか - わからん
   CentOSの起動スクリプトを書き方(+注意点) | 本日も乙