스크립트의 지속적인 핑 루프

스크립트의 지속적인 핑 루프

저는 맞춤형 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의 답변은 훌륭하지만 네트워크 팽창을 피할 것입니다.

하지만 먼저옆에; ping8.8.8.8까지 걸리는 시간은 0.002초밖에 안 걸리므로 저지연 네트워크를 테스트하고 싶다면,

$ timeout 0.1 ping -c 1 8.8.8.8

1/10초의 테스트 시간을 보장하는 데 사용할 수 있습니다(ping에는 1초 미만의 대기 시간이 없으므로).

지금답변속도와 네트워크 사용량을 최적화하세요. 스크립트가 매개변수를 전달하도록 해야 합니다.

#!/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. 전체 아이디어는 주로 모뎀 연결을 위해 만들어졌습니다. 핑 대기 시간은 신호 강도에 따라 달라집니다. 신호 강도가 낮지만 연결이 여전히 유지되는 경우 안정적인 확인을 위해 핑 확인 간격을 1초 이상 낮출 수 있는지조차 확신할 수 없습니다. 그렇기 때문에 쉽게 접근할 수 있는 장소에 결과를 출력하는 기본 간격의 핑 루프가 최선의 절충안이 될 것이라고 생각합니다.

제가 최근에 사용하고 있는 것이 바로 이것입니다

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

관련 정보