LoginSignup
23
26

More than 5 years have passed since last update.

スクリプトで無線LANにWi-Fi接続する -Linux編 (Raspberry Pi対応)-

Last updated at Posted at 2015-11-21

Wi-Fiダイレクトで直接デバイスに無線接続するときに、いちいち/etc/network/interfacesをいじってifdown wlan0 && ifup wlan0とかしていた訳ですが、いかんせん面倒くさい。
そこで、SSIDとパスワードを指定するだけでお手軽に接続できるスクリプトを作りました。
Raspbian Wheezy、Ubuntu14.04で動作確認済みです。ちなみにMac編はこちらです。

wificonn_linux.sh
#!/bin/bash
set -u
export LANG="C"

function usage() {
  cat <<EOT
Usage: bash ${0##*/} <interface-name> <network-SSID> <password>
EOT
}

# 引数チェック
if [ $# -ne 3 ]; then usage && exit 1; fi

# 指定されたインターフェースが存在するか調べる
iwconfig $1 > /dev/null 2>&1
if [ $? -ne 0 ]; then
  echo "Device named '$1' not found."
  exit 2
fi

# すでに接続されていれば終了
iwconfig $1 | grep -wq "ESSID:\"$2\"" && ifconfig $1 | grep -q 'inet addr'
if [ $? -eq 0 ]; then
  echo "Already connected."
  exit 0
fi

# インターフェースを再起動
ifconfig $1 down
ifconfig $1 up
if [ $? -ne 0 ]; then
  echo "Failed to activate interface $1"
  exit 4
fi

# 指定のSSIDを持つアクセスポイントがあるか調べる
iwlist $1 scan | grep -wq "ESSID:\"$2\""
if [ $? -ne 0 ]; then
  echo "The wi-fi network with SSID:'$2' not found."
  exit 3
fi

# wpa_supplicantが動いていたら殺す
pkill -f "wpa_supplicant.+-i *$1 .*"

# SSIDを設定
iwconfig $1 essid $2

# WPA認証タイムアウト秒数
WPA_AUTH_TIMEOUT=20
is_connected=false
current_time=$(date +%s)
# wpa_supplicantをnohupで起動し接続。stdbufはバッファリングを防止するために必要
while read -t ${WPA_AUTH_TIMEOUT} line; do
  echo "  $line"
  echo $line | grep -wq 'CTRL-EVENT-CONNECTED'
  if [ $? -eq 0 ]; then
    is_connected=true
    break
  fi
  # タイムアウト判定
  if [ $(($(date +%s) - ${current_time})) -gt ${WPA_AUTH_TIMEOUT} ]; then
    echo "Timeout."
    break
  fi
done < <(nohup bash -c "wpa_passphrase $2 $3 | stdbuf -oL wpa_supplicant -i $1 -D wext -c /dev/stdin 2>&1 &")
if ! $is_connected; then
  echo 'WPA authentication failed.'
  pkill -f "wpa_supplicant.+-i *$1 .*"
  exit 5
fi

# IPアドレス割り当て
ifconfig $1 | grep -q 'inet addr'
if [ $? -ne 0 ]; then
  dhclient $1
  ifconfig $1 | grep -q 'inet addr'
  if [ $? -ne 0 ]; then
    echo 'IP address cannot not be assgined.'
    exit 6
  fi
fi

echo 'Connected successfully.'
exit 0

使いかた

$ bash wificonn_linux.sh <interface-name> <network-SSID> <password>
  • 実行にはルート権限が必要です。一般ユーザーはsudoしてください。
  • <interface-name>はwlan0, wlan1などのインターフェース名を指定します。インターフェース名はiwconfigで確認できます(老婆心)。
  • 生のパスワードを入力する必要があるので、共同のマシンでは注意してください。

一応解説

Debian系Linuxで無線LANの設定を行うときは、種々の解説サイトにもあるように

  1. wpa_passphraseの出力をリダイレクトし、PSKの暗号化と同時に設定ファイルを作成する
  2. /etc/network/interfaceswpa-conf <設定ファイルのパス>と書く

のが一般的です。こうしておくとwpa_supplicantが勝手に立ち上がり、設定ファイルを読み込んでよろしく認証を行ってくれます。今回は設定ファイルを使わないため、wpa_supplicantの設定ファイルを-c /dev/stdinとして標準入力に設定し、wpa_passphraseの出力をパイプで流しこむようにしました。

  • wpa_supplicantを起動させたらそのログ出力を一行ずつ読み込んで、OKっぽいログ(CTRL-EVENT-CONNECTED)が出ていたら成功とみなします。もっといい判定方法があるかも?
  • 一定時間以上経ってもダメならタイムアウトエラーにしています。環境によってはWPA_AUTH_TIMEOUTの値を調整する必要があるかもしれません。
  • stdbuf -oLはバッファリング動作を変更するコマンドで、wpa_supplicantが出力をバッファに貯めずに一行ずつ吐き出すようにしています。
  • IPアドレスはdhclientコマンドで動的に割り当てています。

バグや指摘などありましたら、ぜひコメント欄かTwitterの方までお願い致しますm(__)m

23
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
26