私はカスタマイズされた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
はい、そうすることができます。しかし、これは接続を確認するのに非常に悪い方法です。明らかにここには競争条件があります。最初のループが実行されたときに接続がアクティブになっても、2番目のループがアクティブになるという意味ではありません。さらに、スクリプトの先頭からファイルを読み取っても、スクリプトの最後にも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.全体のアイデアは主にモデム接続のために作られています。 ping待ち時間は信号強度に依存します。信号強度が低くても接続が維持されている場合は、安定した確認のためにPing確認間隔を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