MacbookのWi-Fiが不安定で悩まされ続けてきましたが、不具合を自動検出してWi-Fiをoff/onするスクリプトによって安定化に成功しました!
たいした内容ではないですが、効果てきめんだったので共有します。
2019/12/1更新 Macがスリープ復帰した直後かどうかを判定して無駄にWi-Fi再起動しないように修正するとともに、自分で最適と思ったタイマーチューニングをしました。ソースのみ変更しています。
2020/9/6更新 若干の最適化、メッセージの追加修正、ゲートウェイアドレスとWi-Fiデバイス名の自動取得、など対応しました。ソースのみ変更しています。
2022/7/4更新 かなり品質が悪いWi-Fiネットワークに接続した際、起動直後のゲートウェイ取得ができなくて止まってしまう状態を改善しました。ソースのみ変更しています。
2022/10/13更新 バグを修正しました。ソースのみ変更しています。
1. Wi-Fi不安定の症状
こんな症状です。
- MacBook Pro (13-inch, 2018, Four Thunderbolt 3 Ports)。購入時はHigh Sierraでしたが、Mojaveにアップデートした以降に症状がひどくなった気がします。
- Wi-Fiルータは、Buffalo WSR-2533DHPL。
- 使用中のWi-Fiが突然接続できなくなり、しばらく回復しません。Wi−Fiルータとの間のpingが疎通できない状態になります。
- Macbookか接続できない時に、同じWi−Fiをスマホとかで利用できています。そのため、Macbook固有の症状であることがわかります。
- Macbook側の上部メニューバーからWi-Fiを手動でoff/onすると復旧します。
- 発生頻度はバラバラで、数時間発生しないこともあれば、10分以内に再発することもあります。
- ネットでも類似症状は多数報告されていますが、対策として書かれている手段(bluetooth off、IPv6 off、DHCP off、SMCリセット、Wi-Fiルータ側のチャネルを固定する、等)はいずれも効果ありませんでした。
2. 安定化スクリプト
何をやっても解決しなかったのですが、このスクリプトを仕掛けることで、スッキリ解決しました。Wi-Fi不安定時に手動でWi-Fi off/onして復旧させていた動作を、スクリプトで自動化したことになります。
- 以下のスクリプトを、ホームディレクトリ等に置いて、実行可能にして、ターミナルから ./auto_network_recover.sh などで実行してください。あとはターミナルを閉じないで放置しておくだけで、Wi−Fi不具合を自動検出して復旧します。
- sleepタイマーや、ping繰り返し数などは、必要に応じてチューニングしてください。
auto_network_recover.sh
#!/bin/bash
restart_wifi()
{
while :
do
echo 'Try to restart Wi-Fi network.'
networksetup -setairportpower $device off
networksetup -setairportpower $device on
echo 'Restarted Wi-Fi network. Wait a while to recheck.'
sleep 10
target=`networksetup -getinfo Wi-Fi | awk '/^Router/{print $2}'`
device=`networksetup -listallhardwareports | awk '/Wi-Fi/{getline; print $2}'`
if [[ -n "$target" ]]
then
result=`ping -c 2 $target`
if [[ $result =~ 100.0% ]]
then
echo $result
echo 'Failed to ping to gateway.'
else
echo $result
echo 'Succeeded to restart Wi-Fi network.'
break
fi
else
echo 'Failed to detect gateway.'
fi
echo 'Restarting Wi-Fi network again.'
done
}
while :
do
target=`networksetup -getinfo Wi-Fi | awk '/^Router/{print $2}'`
device=`networksetup -listallhardwareports | awk '/Wi-Fi/{getline; print $2}'`
[[ -n "$target" ]] && break
echo 'Cannot detect gateway at' `date`
restart_wifi
done
echo 'Start monitoring gateway:'$target 'via device:'$device 'at' `date`
lasttime=`date +%s`
keep_failed=0
while :
do
if [ $(( $(date +%s) - $lasttime )) -lt 60 ]
then
lasttime=`date +%s`
result=`ping -c 2 $target`
if [[ $result =~ 100.0% ]]
then
echo $result
echo 'Error detected at' `date`
restart_wifi
fi
else
echo 'Wakeup Detected at' `date`
sleep 60
lasttime=`date +%s`
fi
sleep 1
done