脚本中连续 ping 循环

脚本中连续 ping 循环

我正在做一些定制的 Openwrt 编译。我的一些脚本在执行操作之前会执行 ping 操作来测试连接。

if [ "$(ping -c 1 -w 3 8.8.8.8)" ]; then
  do stuff;
else
 echo "no connection"
fi

其中一些运行其他脚本,并且由于ping需要一些时间,运行脚本需要比应有的时间更多的时间,这在某些情况下是一个问题。

我想做某种连续循环,将 0 或 1 写入某个文件。从现在开始,使用 ping 进行连接测试的脚本将测试somefile.

有没有办法写这样的脚本?

答案1

你的意思是不是这么简单:

while :; do
   ping -c 1 -w 3 8.8.8.8; echo $? > /tmp/ping.status
   sleep 1
done

这将每秒写入一次ping退出状态。/tmp/ping.status然后,在另一个脚本中,您可以有类似的内容:

pingFailed=$(cat /tmp/ping.status)
if [ $pingFailed -ne 0 ]; then
    echo "No connection"
else
    echo "Connected!"
fi

所以是的,你可以这样做。然而,这是一种非常糟糕的检查连接的方法。显然,这里存在竞争条件。当第一个循环运行时连接处于活动状态,并不意味着它在第二次处于活动状态。更重要的是,如果您在脚本开头读取文件ping.status,并不意味着连接在脚本末尾仍然存在。此外,您还不断地向您的网络和 CPU 发送垃圾邮件。这实在是不太优雅。

测试连接是否正常(至少在 Linux 上)的一种更快、更简单的方法是查看网卡名称/sys/class/net/$NIC/link_mode$NIC例如,在我的系统上:

## Wireless connection up
$ cat /sys/class/net/wlp3s0/link_mode 
1
## Wireless connection down
$ cat /sys/class/net/wlp3s0/link_mode 
0

您可以编写一个函数来检查这一点:

isLinkDown(){
    return $(cat /sys/class/net/wlp3s0/link_mode)
}

您可以在脚本中使用它,如下所示:

if isLinkDown; then 
    echo Link Down
else
    echo Link Up

答案2

terdon的答案很好,但我会避免网络膨胀,

但首先在旁边;ping到 8.8.8.8 只需 0.002 秒,因此如果您想测试低延迟网络,

$ timeout 0.1 ping -c 1 8.8.8.8

可用于保证 1/10 秒的测试时间(因为 ping 没有亚秒级的等待时间)。

现在回答优化速度和网络使用;你应该让你的脚本传递参数;

#!/bin/bash

usage() {
    echo "Usage: $0 [OPTIONS]"
    echo " OPTIONS:"
    echo "  -h     this Help message"
    echo "  -n     do Not re-test network connectivity"
}

NO_TEST=false
while getopts "nh" OPT; do
    case "$OPT" in
        n)
            NO_TEST=true
            ;;
        h)
            usage
            exit 0
            ;;
        *)
            echo "unsupported option $OPT" >&2
            usage
            exit 1
            ;;
    esac
done
shift $((OPTIND - 1))

if ! $NO_TEST && ! ping -c 1 -w 3 8.8.8.8; then
    echo "no connection" >&2
    exit 2
fi
echo "do stuff";

答案3

谢谢大家的回答!我只是需要一些时间来考虑您的一些宝贵想法。为了澄清一些事情,我只想补充一点:
1. 我不能使用参数,因为大多数脚本要么在 init.d 中工作,要么由 cron 运行。
2. 整个想法主要是为了调制解调器连接而创建的。 ping 延迟取决于信号强度。我什至不确定是否可以将 ping 检查间隔降低到 1 秒以上,以便在信号强度较低但连接仍然存在时进行可靠的检查。这就是为什么我认为具有默认间隔的 ping 循环将结果输出到一些易于访问的地方将是最好的妥协。

这是我最近使用的

modemup(){
    echo -e "AT+QRST=1,0\r\n" > /dev/ttyUSB2
    ifdown $INTERFACE && ifup $INTERFACE

    if [ "$(ifconfig | grep $INTFC_NAME)" ]; then
        return 0
    else
        echo "Cant start modem interface"
        return 1
    fi
  } 

reconnect(){
    MAX_ATTEMPTS=$1 #number of tries before reboot
    TRIES=1

    while [ $TRIES -le $MAX_ATTEMPTS ]; do
        echo "Trying to reconnect ..."
        echo "Number of try: $TRIES"
        modemup
        /etc/init.d/network restart
        sleep 10
        if [ "$(ping -c 1 -w 3 8.8.8.8)" ]; then
            break
        fi
        : $((TRIES+=1))
    done
    echo "Tried $MAX_ATTEMPTS times, couldnt reconnect. Rebooting ..."
    reboot
}

while true; do
    if [ "$(ping -c 1 -w 3 8.8.8.8)" ]; then
         rm -rf $NOCONFILE #if noconnection file exists delete it
    else
        mkdir -p $LOG_DIR/${DAY_DIR}
        TIME=`date +%Y%m%d%H%M%S`
        echo "$TIME: Connection lost" 2>&1 | tee -a $LOG_FILE
        touch $NOCONFILE
        reconnect $ATTEMPTS 2>&1 | tee -a $LOG_FILE   
    fi
    sleep $INTERVAL
done

相关内容