路由器上安装docker,会更改很多网络方面的设置,在openwrt上会影响稳定性(在标准linux系统上暂时没有这个烦恼)。


脚本作用:每10分钟ping一次外网域名,假如列表中的域名全部ping不通则视为断网,连续6次检测到断网则重启系统。
在openwrt上的用法:
1,将脚本复制到/opt/ping_hosts/目录下
2,运行这行命令赋予脚本可执行权限

chmod +x /opt/ping_hosts/ping_hosts.sh

3,将此命令添加到 openwrt-启动项-最下面的启动命令里即可(在exit 0的前面)。

nohup /opt/ping_hosts/ping_hosts.sh &


注意,如果你不插网线,因为一直连不上网,它会让系统每隔60分钟重启一次,无限次数。

如果想在linux上使用,需要自行添加到开机启动,不需要任务计划,开机执行一次即可(后台,就是第三步那行命令)。

脚本内容:

#!/bin/bash

# 获取脚本名和进程号
script_name="$(basename "$0")"
pid=$(pgrep -f "$script_name")

# 如果当前已经有一个实例在运行,则退出
if [ $(echo "$pid" | wc -w) -gt 1 ]; then
    echo "$(date "+%Y-%m-%d %H:%M:%S"): Script is already running with PID $pid. Exiting." >&2
    exit 1
fi

# 定义需要 ping 的域名列表
domain_list=("www.nodeseek.com" "www.baidu.com" "doh.pub" "www.microsoft.com")

# 定义连续 ping 失败次数计数器
ping_fail=0

# 定义全部 ping 失败次数计数器
all_fail=0

# 定义连续全部 ping 失败次数的最大值
max_all_fail=6

# 定义每次 ping 的间隔
ping_interval=600

# 定义重启命令
reboot_cmd="reboot"

# 定义日志文件路径
log_file="/opt/ping_hosts/ping_hosts_log"

# 定义日志保留的秒数
log_seconds=864000

# 创建日志文件(如果不存在)
touch $log_file

# 定义函数来检查并删除日志文件中的过期内容
#function delete_old_logs {
##     计算 log_seconds 秒之前的时间戳
#    threshold=$(date -d "@$(($(date +%s) - $log_seconds))" +%s)

##     使用 sed 命令筛选出超出时间戳的行并写回原文件
#    sed -i -e "/^20[0-9][0-9]-[0-9][0-9]-[0-9][0-9]/!d" -e "/^$(date +%Y-%m-%d)/!d; /^$(date -d @$threshold +'%Y-%m-%d')/q" "$log_file"
#}

# ping_hosts 函数
function ping_hosts {
    for domain in "${domain_list[@]}"
    do
	    output=$(ping -c 1 "$domain")
        if [ $? -ne 0 ]; then
			((ping_fail++))
		    echo "$(date "+%Y-%m-%d %H:%M:%S"): ping $domain :超时, ping_fail=${ping_fail}" | tee -a "${log_file}"
        else
		    time=$(echo "$output" | awk '/time=/ {print $7}' | cut -d '=' -f 2)
		    #echo "$(date "+%Y-%m-%d %H:%M:%S"): ping $domain :${time}ms, ping_fail=${ping_fail}" | tee -a "${log_file}"
        fi
    done
}

# 主循环
while true
do
    # 检查是否需要删除日志文件中的过期内容
    #delete_old_logs

    # 将 ping 记录写入日志文件
    ping_hosts

    # 如果所有域名都 ping 失败
    if [ $ping_fail -eq ${#domain_list[@]} ]; then
	ping_fail=0
	((all_fail++))
	echo "$(date "+%Y-%m-%d %H:%M:%S"): 所有目标均无回复,all_fail+1,现在是 ${all_fail}" | tee -a ${log_file}

        # 如果连续 ping 失败次数达到最大值,则重启系统
        if [ $all_fail -eq $max_all_fail ]; then
            echo "$(date "+%Y-%m-%d %H:%M:%S"): 连续失败次数已达最大:$all_fail / ${max_all_fail}" | tee -a "${log_file}"
            echo "$(date "+%Y-%m-%d %H:%M:%S"): 正在将失败次数置零,正在重启系统..." | tee -a $log_file
			echo "$(date "+%Y-%m-%d %H:%M:%S")" | tee -a "${log_file}"
			all_fail=0
            $reboot_cmd
        fi
        # 等待指定时间(秒)后再次执行
        sleep $ping_interval
		
    else
        # 如果有一个或多个域名可达,则将连续 ping 失败次数重置为 0
        ping_fail=0
		all_fail=0
        #echo "$(date "+%Y-%m-%d %H:%M:%S"): 执行成功,数据已清零。 " | tee -a "${log_file}"
        #echo "$(date "+%Y-%m-%d %H:%M:%S")" | tee -a "${log_file}"

        # 等待指定时间(秒)后再次执行
        sleep $ping_interval
    fi

done