yynsmk's tech blog

何でもできる=何にもできない

ネットワークの環境設定をスクリプトで自動で変更できるようにするには?

これまで、ネットワークの環境設定(自動とか固定IPとか)を手動で変更していました。
今回は、自分の勉強も兼ねてそれをシェルスクリプトで自動化してみます。

以下の記事が非常に参考になりました。ありがとうございます🙇‍♂️ qiita.com

作成したコードはGitHubにあげました。
github.com

コマンドによる設定の変更

macのネットワーク設定は、GUIの他に以下の2つのコマンドを使ってもできます。

  • networksetup
  • scselect

scselectよりもnetworksetupのほうができることの幅が広いです。
設定の変更自体はどちらのコマンドでも可能です。

networksetup

インタフェースにつながっているネットワークの情報を表示

$ networksetup -getairportnetwork en0
Current Wi-Fi Network: <SSID>

現在のネットワーク設定を表示

$ networksetup -getcurrentlocation
Automatic

ネットワーク設定の変更

$ networksetup -switchtolocation <変更したい設定>
found it! %

Wi-FiのON/OFFの表示

$ networksetup -getairportpower en0
Wi-Fi Power (en0): On

scselect

ネットワークの設定一覧を表示(*が現在の設定)

$ scselect 
Defined sets include: (* == current set)
 * xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (Automatic)
   xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (University)

ネットワーク設定の変更

$ scselect Automatic
CurrentSet updated to  xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (Automatic)

自動化スクリプトの作成

スクリプトは基本的に参考サイトのものを使えば問題ないのですが、一部自分なりに変更を加えました。
おおまかな処理の流れはこんな感じです。

  1. Wi-FiがOFFになっていたらONに変える
  2. SSIDの値(ネットワーク名)に応じて、指定の設定に変更する

以下が完成したスクリプトです。

#!/bin/sh
ADAPTER="<インタフェース名>"

# Wi-FiがOFFならONに変える
airportpower=`networksetup -getairportpower ${ADAPTER} | awk -F ': ' '{print $2}'`
if test ${airportpower} = 'Off'; then
  networksetup -setairportpower ${airportpower} on
  sleep 3
fi

# 設定とSSIDを引数にして設定を変更してデスクトップに通知するメソッド
switch_location() {
    currentlocation=`networksetup -getcurrentlocation`
    if test $currentlocation = $1; then
        return
    fi
    scselect ${1}
    # networksetup -switchtolocation ${1}
    osascript -e 'display notification "'"ネットワーク環境を「${1}」へ変更しました。"'" with title "'"${0##*/}"'" subtitle "'"${2}"'"'
}

# 取得したSSIDの値に応じて設定を振り分ける
SSID=`networksetup -getairportnetwork ${ADAPTER} | awk -F ': ' '{print $2}'`
case "$SSID" in
  "<SSID>")
    switch_location "<変更したい設定>" ${SSID}
    ;;
  *)
    switch_location "Automatic" ${SSID}
    ;;
esac

デスクトップ通知にはAppleScriptを使います。
以下のコードで通知が出せます。

display notification "本文" with title "タイトル" subtitle "サブタイトル" sound name "サウンド名"

AppleScriptをターミナルまたはシェルスクリプトから動かすには、スクリプトを文字列にしてosascript -eを付けます。

SSIDの変更を検知してスクリプトを自動実行

先程のスクリプトを自動実行するには、Launch Agentsを利用します。
Launch Agentsにスクリプトを登録することで何らかのイベント発生時に自動実行することが可能です。

ちなみに、SSIDの変更検知は/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plistを監視することで分かります。
ネットワーク関連の何かしらに変化があるとこのファイルも変更されるみたいです。

Launch Agentsについては以下のサイトが分かりやすかったです。

takuya-1st.hatenablog.jp

このサイトの通りに、plistを作って、シンタックスを確認して、ロードして、一覧で確認できれば登録完了です!

※追記:plistは~/Library/LaunchAgentsに置く必要があります。

plistの作成

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>Lauch Agentへの登録名</string>
  <key>ProgramArguments</key>
  <array>
    <string>実行したいスクリプトの絶対パス</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
  <key>WatchPaths</key>
  <array>
    <string>/Library/Preferences/SystemConfiguration/com.apple.airport.preferences.plist</string>
  </array>
</dict>
</plist>

シンタックスの確認

$ plutil -lint <path to plist>
<path to plist>: OK

plistのロード

$ launchctl load <path to plist>

登録の確認

$ launchctl list | grep <plistのラベル>
-       0       <path to plist>

おわりに

無事にできました〜!
個人的に非常に学びが多くてやった甲斐がありました。
また、何かおもしろそうなことがあればやってみようと思います。