Openwrt 自动重启网卡脚本,解决运营商强制释放IP引起的无网络问题

其他内容

本文最后更新于 2024年7月8日   请注意相关内容可能已过时

用宽带的都知道,国内的运营商的都有定时强制断线重拨的功能.由于民用宽带的价格问题,所以运营商是不可能给你用固定IP的,甚至很多地方连公网IP都没有.需要自己联系运营商获取.

而运营商为了防止你使用的某个IP时间过长,一般在你的设备拨号成功以后每间隔几天就会强制断网重拨一次.

很多人用Openwrt作为软路由的系统.用来负责拨号上网.但是Openwrt有一个一直以来都有的Bug,就是在运营商强制断线重连以后有概率没有网络,即便是你已经拨号成功给你分配了IP.

所以我用了一个脚本来解决这个问题.

通过定时PING指定IP来检测网络是否畅通.如果不通就会重启网卡.

为了排除有时候是运营商的故障.连续重启3次网卡以后就不会继续重启了.脚本会生成一个文件用来记录重启的次数,待网络恢复以后,该文件又会重置为0.

以下是脚本内容和启动脚本.附带安装方法.

配置运行的脚本文件

在/root 目录下面新建一个文件为  network_check.sh

sudo touch /root/network_check.sh
sudo vi /root/network_check.sh

复制以下内容并保存,看不懂没关系.都有注释.目标IP可以改成任意.我这里使用的是四川联通的DNS服务器地址.

#!/bin/sh

# 日志和重启计数文件目录
LOG_DIR="/root/reboot_log"
REBOOT_COUNT_FILE="$LOG_DIR/reboot_count.log"
LOG_FILE="$LOG_DIR/network_check.log"
OLD_LOG_FILE="$LOG_DIR/network_check.log.old"
LOCK_FILE="/var/run/network_check.lock"

# 目标IP地址
TARGET_IP="119.6.6.6"

# 每次检查网络连接的间隔时间(秒)
INTERVAL=300  # 5分钟

# 超出重启次数限制后重启WAN口的间隔时间(秒)
WAN_RESTART_INTERVAL=600  # 10分钟

# 重启次数限制
REBOOT_LIMIT=3

# 每次 ping 操作的次数和超时时间
PING_COUNT=3
PING_TIMEOUT=2

# 等待获取网络的时间(秒)
NETWORK_WAIT=30  # 30秒

# 创建日志目录(如果不存在)
mkdir -p $LOG_DIR

# 轮替日志文件
if [ -f $LOG_FILE ]; then
    mv $LOG_FILE $OLD_LOG_FILE
fi
# 记录日志
log_message() {
    echo "$(date +"%Y-%m-%d %H:%M:%S") - $1" | tee -a $LOG_FILE
}

# 检查是否已有实例在运行
if [ -f $LOCK_FILE ]; then
    log_message "发现已有实例在运行,退出"
    exit 1
fi

# 创建锁文件
touch $LOCK_FILE

# 清理函数,删除锁文件
cleanup() {
    rm -f $LOCK_FILE
    exit 0
}

# 捕捉脚本退出信号,清理锁文件
trap cleanup INT TERM EXIT

# 脚本启动后,先等待一段时间再开始检查网络
log_message "脚本启动后,等待 $NETWORK_WAIT 秒以确保网络连接"
sleep $NETWORK_WAIT

# 初始化重启次数达到限制的标志
reboot_limit_reached=false

while true; do
    # 获取当前时间
    CURRENT_TIME=$(date +"%Y-%m-%d %H:%M:%S")

    # 进行多次 ping 操作
    if ping -c $PING_COUNT -W $PING_TIMEOUT $TARGET_IP > /dev/null; then
        log_message "网络畅通"
        reboot_count=0  # 重置重启计数
        echo $reboot_count > $REBOOT_COUNT_FILE  # 更新文件
        reboot_limit_reached=false  # 网络畅通时重置标志
    else
        log_message "网络不通"

        # 读取当前的重启计数
        if [ -f $REBOOT_COUNT_FILE ]; then
            reboot_count=$(cat $REBOOT_COUNT_FILE)
        else
            reboot_count=0
        fi

        # 判断是否达到重启次数限制
        if [ $reboot_count -ge $REBOOT_LIMIT ]; then
            if [ "$reboot_limit_reached" = false ]; then
                log_message "重启次数达到限制,尝试每隔 $WAN_RESTART_INTERVAL 秒重启一次WAN口"
                reboot_limit_reached=true  # 设置标志
            fi
        else
            reboot_count=$((reboot_count+1))  # 增加重启计数
            echo $reboot_count > $REBOOT_COUNT_FILE  # 更新文件
            log_message "重启计数: $reboot_count,重启 WAN 接口"
            ifdown WAN; sleep 5; ifup WAN  # 重启 WAN 接口
            log_message "重启 WAN 接口后,等待 $NETWORK_WAIT 秒以确保网络连接稳定"
            sleep $NETWORK_WAIT  # 等待 WAN 接口稳定
        fi
    fi

    # 如果达到重启次数限制,每隔 WAN_RESTART_INTERVAL 秒重启一次WAN口
    if [ "$reboot_limit_reached" = true ]; then
        log_message "由于重启次数达到限制,重启 WAN 接口"
        ifdown WAN; sleep 5; ifup WAN  # 重启 WAN 接口
        log_message "重启 WAN 接口后,等待 $NETWORK_WAIT 秒以确保网络连接稳定"
        sleep $NETWORK_WAIT  # 等待 WAN 接口稳定
        sleep $WAN_RESTART_INTERVAL  # 等待 WAN_RESTART_INTERVAL 时间进行下一次检测
    else
        # 等待指定的间隔时间
        sleep $INTERVAL
    fi
done

# 清理锁文件
cleanup

 

脚本逻辑详解

  1. 变量定义
    • 设置日志文件、重启计数文件、锁文件的位置以及一些配置参数,如目标IP、检查间隔时间、重启限制次数等。
  2. 创建日志目录
    • 使用 mkdir -p 命令确保日志目录存在,如果不存在则创建。
  3. 日志记录函数
    • log_message 函数用于记录日志信息,包括时间戳。
  4. 防止多实例运行
    • 检查锁文件是否存在。如果锁文件存在,说明脚本已经在运行,记录日志并退出。
    • 如果锁文件不存在,则创建锁文件。
  5. 清理函数
    • cleanup 函数用于删除锁文件并退出脚本。
    • 使用 trap 捕捉脚本退出信号(如 INTTERM),确保脚本退出时能够执行清理函数。
  6. 启动后等待
    • 记录日志并等待 POST_START_WAIT 秒,确保网络有时间连接。
  7. 主循环
    • 进入一个无限循环,定期检查网络连接状态。
  8. 网络检查
    • 使用 ping 命令检测目标IP是否可达。
    • 如果网络畅通:
      • 记录日志。
      • 将重启计数重置为0,并更新重启计数文件。
      • reboot_limit_reached 标志设置为 false
    • 如果网络不通:
      • 记录日志。
      • 读取当前的重启计数。如果文件不存在,则重启计数设置为0。
      • 判断是否达到重启次数限制。
        • 如果达到重启次数限制,记录日志并设置 reboot_limit_reached 标志为 true
        • 如果未达到重启次数限制,增加重启计数,更新重启计数文件,记录日志,并重启WAN接口(ifdown WAN; sleep 2; ifup WAN)。
  9. 重启WAN接口
    • 如果达到重启次数限制,脚本每隔 WAN_RESTART_INTERVAL 秒重启一次WAN接口,记录日志。
    • 如果未达到重启次数限制,则按正常的 INTERVAL 时间进行网络检查。
  10. 清理锁文件
    • 在主循环结束后(在本例中不会发生),执行 cleanup 函数删除锁文件。

赋予脚本执行权限

chmod +x /root/network_check.sh

 

创建和配置启动脚本

1.创建启动脚本文件

sudo touch /etc/init.d/network_check
sudo vi /etc/init.d/network_check

2.编辑启动脚本文件

#!/bin/sh /etc/rc.common

START=95

PID_FILE="/var/run/network_check.pid"
LOCK_FILE="/var/run/network_check.lock"

start() {
    if [ -f $PID_FILE ]; then
        PID=$(cat $PID_FILE)
        if [ -n "$PID" ] && kill -0 $PID 2>/dev/null; then
            echo "Network check script is already running with PID $PID"
            return 1
        fi
    fi

    echo "Starting network check script"
    /root/network_check.sh &
    echo $! > $PID_FILE
}

stop() {
    if [ -f $PID_FILE ]; then
        PID=$(cat $PID_FILE)
        if [ -n "$PID" ]; then
            echo "Stopping network check script"
            kill $PID  # 发送 SIGTERM (15)
            sleep 5   # 等待 5 秒以便进程有时间进行清理和退出

            # 检查进程是否已终止
            if kill -0 $PID 2>/dev/null; then
                echo "Process did not terminate, sending SIGKILL"
                kill -9 $PID  # 强制终止进程
            fi

            rm -f $PID_FILE  # 删除 PID 文件
            rm -f $LOCK_FILE  # 删除锁文件
        fi
    else
        echo "PID file not found, script may not be running"
    fi
}

restart() {
    stop
    sleep 1
    start
}

enabled() {
    # 检查服务是否设置为自动启动
    if [ -f "/etc/rc.d/S${START}network_check" ]; then
        echo "Network check script is enabled"
    else
        echo "Network check script is not enabled"
    fi
}

status() {
    if [ -f $PID_FILE ]; then
        PID=$(cat $PID_FILE)
        if [ -n "$PID" ] && kill -0 $PID 2>/dev/null; then
            echo "Network check script is running with PID $PID"
        else
            echo "Network check script is not running, but PID file exists"
        fi
    else
        echo "Network check script is not running"
    fi
}

 

启用和测试脚本

  1. 赋予启动脚本执行权限
    chmod +x /etc/init.d/network_check
  2. 启用启动脚本
    /etc/init.d/network_check enable
  3. 手动启动脚本
    /etc/init.d/network_check start
  4. 检查脚本状态
    /etc/init.d/network_check status
  5. 手动停止脚本
    /etc/init.d/network_check stop
  6. 查看日志文件

    cat /root/reboot_log/network_check.log

保存完成以后重启一下设备.在ssh里面输入

ps | grep network_check

就可以看到脚本是否有在运行了.也可以通过上面的查看日志文件的命令,会发现已经开始有内容了.

有任何Bug或者使用上的问题也欢迎留言讨论

3 个评论在 “Openwrt 自动重启网卡脚本,解决运营商强制释放IP引起的无网络问题



  1. network_check.sh 好像也需要执行权限

    1. 是的,我忘记了,等我有空添加上去!
      使用 chmod +x /root/network_check.sh 即可

发表评论

邮箱地址不会被公开。 必填项已用*标注