想必,大多数人都是跟我一样玩树莓派的,把树莓派作为一台服务器,接入路由器下的局域网。没有显示器,也没有用TTL。树莓派的控制可以用SSH。然而,要是路由器死机重启,树莓派就失去控制了。另外,树莓派运行多天后好像也有断网的情况。遇到这种情况,就只能暴力的拔电源了。有木有一种和平一点的方式呢。自然,这是有的。搜罗了整个互联网,总算是找了两个挺不错的解决方案。

方案一(爱板网 树莓派教程三——自动断网重连)

这是我找到的第一个方案,它需要两个定时任务,一个用于网络不通时重启网络,另一个用于长时间网络不通时重启系统。原理是获得预设网站连接后返回的参数,如果正常访问则计数器加1,当计数器记录的个数等于0时,就重启网络。长时间网络不通,则重启树莓派。

下面正式讲述该方案的具体内容

  1. 该方案的脚本中调用了curl命令,因此需要安装curl工具
    1
    
    sudo apt-get install curl
    
  2. /etc/network/if-down.d/目录创建检测网络重启网络的脚本net_restart.sh
    1
    
    sudo nano /etc/network/if-down.d/net_restart.sh
    

    然后在该文件中写入以下代码

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    
    #!/bin/bash
    #value define
    urls=("www.baidu.com" "www.2345.com/?kuwait")
    http_code=("200" "301" "302" "404")
    count=${#urls}
    connected=0
       
    echo "now start to check net is on or not!"
    echo "bash file in /etc/network/if-down.d/net_restart.sh"
    #check net is conneted or not
    for ((i=0; i < $count; i++))
    do
        url=${urls[$i]}
        result=$(curl -o /dev/null -s -m 10 -w %{http_code} $url)
        for flag in ${http_code}
        do
            if [ $flag = $result ];then
                connected=$(expr $connected + 1)
            fi
        done
    done
    #if net is down then restart
    if [ $connected -eq 0 ];then
        echo "network is not very well !"
        echo "now restart net !"
        /etc/init.d/networking restart
        /sbin/ifup wlan0
        /sbin/ifup eth0
    fi
    

    然后ctrl+o保存,ctrl+x退出 给net_restart.sh添加可执行权限

    1
    
    sudo chmod +x /etc/network/if-down.d/net_restart.sh
    
  3. 同理在/etc/network/if-down.d/目录创建检测网络重启系统的脚本net_reboot.sh
    1
    
    sudo nano /etc/network/if-down.d/net_restart.sh
    

    然后在该文件中写入以下代码

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    
    #!/bin/bash
    #value define
    urls=("www.baidu.com" "www.2345.com/?kuwait")
    http_code=("200" "301" "302" "404")
    count=${#urls}
    connected=0
    
    echo "now start to check net is on or not!"
    echo "bash file in /etc/network/if-down.d/net_restart.sh"
    #check net is conneted or not
    for ((i=0; i < $count; i++))
    do
        url=${urls[$i]}
        result=$(curl -o /dev/null -s -m 10 -w %{http_code} $url)
        for flag in ${http_code}
        do
            if [ $flag = $result ];then
                connected=$(expr $connected + 1)
            fi
        done
    done
    #if net is down then reboot
    if [ $connected -eq 0 ];then
        echo "network is not very well !"
        echo "now start to reboot !"
        killall motion
        reboot
    fi
    

    然后ctrl+o保存,ctrl+x退出 再同样给net_reboot.sh添加可执行权限

    1
    
    sudo chmod +x /etc/network/if-down.d/net_reboot.sh
    
  4. 试运行脚本
    1
    2
    
    sudo /etc/network/if-down.d/net_restart.sh
    sudo /etc/network/if-down.d/net_reboot.sh
    
  5. 测试脚本是否能正常工作
    1
    
    sudo ip link set eth0 down && sudo ip link set wlan0 down && sudo /etc/network/if-down.d/net_restart.sh && sudo /etc/network/if-down.d/net_reboot.sh
    
  6. 最后添加定时任务
    1
    
    sudo crontab -e
    

    在文末添加以下代码

    1
    2
    
    */20 * * * * /etc/network/if-down.d/net_restart.sh
    0 17 */1 * * /etc/network/if-down.d/net_reboot.sh
    

    该定时任务的意思是,每隔20分钟,执行net_restart.sh脚本,每天17:00执行net_reboot.sh脚本

  7. 最后,重启定时任务程序,让定时任务生效
    1
    
    sudo /etc/init.d/cron restart
    

    仔细对比上面两个脚本的代码,会发现代码的主体部分都是一样的,只是最终激发的动作不同而已:一个是重启网络,一个是重启系统。我觉得该方案稍微有点繁琐了,不能及时解决问题,并且还一定要连上外网才行。不过,不管黑猫白猫,抓到老鼠就是好猫,这个方案能用就行了。 至此,方案一的内容就结束了。下面你就可以人为断开网络试试咯。

方案二(hugozhu)

好东西是要用来压轴的,这个方案是我前不久找到的,代码简洁,易用,我非常喜欢。一般而言,该方案是针对树莓派连接路由器的情况。其实,我觉得这个方法更通用。只要能指导路由器所连网络上游的服务器的ip即可。假设路由器的ip是192.168.1.1

该方案的原理是,每隔15分钟检查一下,树莓派能否ping通路由器,如果不能,则重启网络。重启网络后再次检测,如果还不通,则重启系统。同时在指定目录生成日志文件。

下面开始该方案的具体讲述

  1. 首先,和第一个方案一样,在/etc/network/if-down.d/目录创建检测网络的脚本checknetwork.sh 然后在该文件中写入以下代码
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    
    #!/bin/bash
    
    #export PATH=/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin
    
    ping_count() {
        count=0
        `timeout 5 ping 192.168.1.1 | while read LINE; do
        {
            if [[ "${LINE}" =~ "64 bytes from" ]]; then
                let "count = $count + 1"
                echo "export count=$count"
            fi
        }
        done`
    echo $count
    }
    
    #echo $(ping_count)
    
    if [[ $(ping_count) < 1 ]]; then
        #ifconfig wlan0
        #ifconfig wlan0 down
        #sleep 1
        #ifconfig wlan0 up
        #sleep 1
        #netcfg -r wlan0
        #sleep 5
        echo "Error: network is down , restarting network now..."
        /etc/init.d/networking restart
        /sbin/ifup wlan0
        /sbin/ifup eth0
        sleep 5
        if [[ $(ping_count) < 1 ]]; then
            echo "Fatal error: wifi is down , rebooting now..."
            reboot
        fi
    fi
    

    然后ctrl+o保存,ctrl+x退出 同样,给checknetwork.sh添加可执行权限

    1
    
    sudo chmod +x /etc/network/if-down.d/checknetwork.sh
    
  2. 试运行脚本
    1
    
    sudo /etc/network/if-down.d/checknetwork.sh
    
  3. 测试脚本是否能正常工作
    1
    
    sudo ip link set eth0 down && sudo ip link set wlan0 down && sudo /etc/network/if-down.d/checknetwork.sh
    
  4. 接下来创建定时任务
    1
    
    sudo crontab -e
    

    在文末添加以下内容

    1
    
    */20 * * * * /etc/network/if-down.d/checknetwork.sh >> /home/pi/checknetwork.log 2>&1
    
  5. 最后,重启定时任务程序,让定时任务生效
    1
    
    sudo /etc/init.d/cron restart
    

    至此,方案二讲述结束。可以愉快的玩耍了。

参考文章