2018年1月1日 星期一

樹莓派自動偵測網路斷線時重開機的方法

這兩周因為在學 R 語言, 無暇玩樹莓派. 不過最近有注意到, 奇怪, 為何都沒收到鄉下樹莓派主機傳送的 IP Changed 的郵件? 難道這個禮拜 ADSL 的浮動 IP 都沒變? 不太可能啊! 周六晚上回到鄉下檢查樹莓派才知是沒有連上無線基地台, 我猜是信舟這台 AP 有時會卡住, 我叫爸遇到 WiFi 無法上網時就去重開 AP 電源, 但 AP 重啟後樹莓派不是應該會自動再連線嗎? 有待細究. 總之, 我將樹莓派重開機後就正常連線了, 馬上就收到 IP Changed 郵件通知.

看來只有自動偵測 IP 變化是不夠的, 還得偵測網路連線是否正常. 如果因為 AP 重啟, 而樹莓派又沒有自動去連線, 就抓不到外網 IP, 當然也送不出郵件來. 經爬文找到下面這篇文章, 剛好就是我遇到的問題及解決辦法, 呵呵, 得來實在不費工夫, 感謝原作之分享 :

Rebooting the Raspberry Pi when it loses wireless connection

作者的解決辦法其實很簡單, 就是寫一個如下的 shell 程式放在 /usr/local/bin 底下, 賦予可執行權限, 然後在 crontab 中加一條定時工作週期性執行此程式來檢查網路連線, 如果發現連線有問題就重啟樹莓派 :

ping -c4 192.168.2.2 > /dev/null
if [ $? != 0 ]
then
  sudo reboot
fi

程式第一行是用來 ping 無線網路上的某個主機, 通常是無線基地台的 IP, 這也是程式中唯一要改的地方. 此 ping 指令若網路連線正常將無回應值, 使得 $? 為 0 而不會去執行 then 的 reboot; 反之當連線異常時就會有回應值, $? 即不為 0 導致 reboot 指令被執行.

首先用 nano 編輯 checkwifi.sh 程式, 輸入上述程式後按 Ctrl+O 與 Ctrl+X 存檔 :

pi@raspberrypi:~ $ nano checkwifi.sh   

然後將此指令複製到 /usr/local/bin 下, 並賦予可執行權限 :
pi@raspberrypi:~ $ sudo cp checkwifi.sh /usr/local/bin/checkwifi.sh    
pi@raspberrypi:~ $ sudo chmod 775 /usr/local/bin/checkwifi.sh   

但是執行此程式卻出現語法錯誤 :

pi@raspberrypi:~ $ sudo /usr/local/bin/checkwifi.sh
/usr/local/bin/checkwifi.sh: 6: /usr/local/bin/checkwifi.sh: Syntax error: end of file unexpected (expecting "then")

查詢 shell script 語法確認程式語法正確, 怎會如此呢? 以錯誤訊息查詢發現 stackoverflow 已有人遇到過此問題並提出解答, 參考 :


"I have met the same problem. And the problem is the format of the file is "dos", but in linux shell requires "unix", so I install the "dos2unix""

原來即使用 nano 編輯的 shell 程式還是 DOS 格式, 須安裝 dos2unix 來將其改為 Unix 格式 :

pi@raspberrypi:~ $ sudo apt-get install dos2unix     
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
  dos2unix
0 upgraded, 1 newly installed, 0 to remove and 198 not upgraded.
Need to get 75.9 kB of archives.
After this operation, 204 kB of additional disk space will be used.
Get:1 http://mirrordirector.raspbian.org/raspbian/ jessie/main dos2unix armhf 6.0.4-1 [75.9 kB]
Fetched 75.9 kB in 6s (12.0 kB/s)
Selecting previously unselected package dos2unix.
(Reading database ... 123331 files and directories currently installed.)
Preparing to unpack .../dos2unix_6.0.4-1_armhf.deb ...
Unpacking dos2unix (6.0.4-1) ...
Processing triggers for man-db (2.7.0.2-5) ...
Setting up dos2unix (6.0.4-1) ...

安裝完畢後用 dos2unix 將 checkwifi.sh 改成 Unix 格式即可正常執行了 :

pi@raspberrypi:~ $ dos2unix checkwifi.sh   
dos2unix: converting file checkwifi.sh to Unix format ...
pi@raspberrypi:~ $ sudo cp checkwifi.sh /usr/local/bin/checkwifi.sh    
pi@raspberrypi:~ $ sudo chmod 775 /usr/local/bin/checkwifi.sh   
pi@raspberrypi:~ $ sudo /usr/local/bin/checkwifi.sh     
pi@raspberrypi:~ $

接下來就是修改 crontab, 設定每小時執行一次 checkwifi.sh, 若連線異常就重啟樹莓派 :

pi@raspberrypi:~ $ crontab -e   
  GNU nano 2.2.6        File: /tmp/crontab.HDz47N/crontab

# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
#
# m h  dom mon dow   command
*/10 * * * * /usr/bin/python2 /home/pi/reportip2.py
0 * * * * sudo /usr/local/checkwifi.sh    

這樣應該就萬無一失了.  查看 crontab 日誌表可知 checkwifi.sh 在整點時有正常執行 :

pi@raspberrypi:~ $ sudo cat /var/log/cron.log 
.....
Jan  1 12:50:02 raspberrypi CRON[23625]: (pi) MAIL (mailed 101 bytes of output b                                                                             ut got status 0x0001 from MTA#012)
Jan  1 13:00:01 raspberrypi CRON[23682]: (pi) CMD (/usr/bin/python2 /home/pi/rep                                                                             ortip2.py)
Jan  1 13:00:01 raspberrypi CRON[23684]: (pi) CMD (sudo /usr/local/checkwifi.sh)
Jan  1 13:00:01 raspberrypi CRON[23674]: (pi) MAIL (mailed 49 bytes of output bu                                                                             t got status 0x0001 from MTA#012)
Jan  1 13:00:02 raspberrypi CRON[23675]: (pi) MAIL (mailed 101 bytes of output b                                                                             ut got status 0x0001 from MTA#012)
Jan  1 13:09:01 raspberrypi CRON[23708]: (root) CMD (  [ -x /usr/lib/php5/sessio                                                                             nclean ] && /usr/lib/php5/sessionclean)
Jan  1 13:10:01 raspberrypi CRON[23751]: (pi) CMD (/usr/bin/python2 /home/pi/rep                                                                             ortip2.py)
Jan  1 13:10:02 raspberrypi CRON[23747]: (pi) MAIL (mailed 101 bytes of output b                                                                             ut got status 0x0001 from MTA#012)
Jan  1 13:17:01 raspberrypi CRON[23837]: (root) CMD (   cd / && run-parts --repo                                                                             rt /etc/cron.hourly)
Jan  1 13:20:01 raspberrypi CRON[23855]: (pi) CMD (/usr/bin/python2 /home/pi/rep                                                                             ortip2.py)
Jan  1 13:20:02 raspberrypi CRON[23851]: (pi) MAIL (mailed 101 bytes of output b                                                                             ut got status 0x0001 from MTA#012)
Jan  1 13:30:01 raspberrypi CRON[23897]: (pi) CMD (/usr/bin/python2 /home/pi/rep                                                                             ortip2.py)
Jan  1 13:30:02 raspberrypi CRON[23893]: (pi) MAIL (mailed 101 bytes of output b                                                                             ut got status 0x0001 from MTA#012)
Jan  1 13:39:01 raspberrypi CRON[23920]: (root) CMD (  [ -x /usr/lib/php5/sessio                                                                             nclean ] && /usr/lib/php5/sessionclean)
Jan  1 13:40:01 raspberrypi CRON[23965]: (pi) CMD (/usr/bin/python2 /home/pi/rep                                                                             ortip2.py)
Jan  1 13:40:02 raspberrypi CRON[23961]: (pi) MAIL (mailed 101 bytes of output b                                                                             ut got status 0x0001 from MTA#012)

關於 crontab 日誌紀錄開啟方式參考 :

從外網以 SSH 存取樹莓派的方法

2018-01-02 補充 :

早上 07:00 手機收 mail 就收到樹莓派傳來的最新 IP 為 114.27.99.134 :




這兩天觀察 IP 變換頻率不定, 昨天一天一次, 今天則已變換兩次. 每當我要連線操控鄉下的 Pi 3 時就在手機信箱中找最近一次的 [RPI] IP CHANGED 標題的郵件, 再開啟手機 App JuiceSSH 1編輯連線 IP 即可, 不須開啟電腦也能透過 Internet 控制 Pi 3, 操作如下 :

首先按 JuiceSSH 最上方的連線 (管理您的連線) :




按住所要編輯的連線 (此處為中間的 Raspberry Pi 3) :



選編輯 :



更改主機欄為最新的 IP, 然後務必按右上角的勾勾才會儲存進去 :




按左上角的 <- 更新連線回到 JuiceSSH 首頁, 點 "常用" 中剛剛編輯好新 IP 的連線 (此處為 Raspberry Pi 3) 就會建立連線了 :



有 JuiceSSH 真好用.

2018-01-08 補充 :

觀察本周收到的 IP_CHANGED 郵件如下 :




有時候一天變化多次 (1 月 3 日就三次), 有時好幾天都不變, 例如 1/4~1/5 都沒變. 或許 1/3 的多次變化是因為自動重開機, 但上面的 Shell script 沒有紀錄重開機事件, 因此無法印證. 有空要修改程式, 在 reboot 前把時間紀錄到一個文字檔中.

沒有留言 :