저는 맞춤형 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에는 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