私はbashシェルスクリプトで私のサーバーの1つに対してURL呼び出しを実行する必要があるプロジェクトを進めています。
http://hostname.domain.com:8080/beat
上記のURLをクリックすると、次の応答が表示され、それを解析してsyncs
値を抽出する必要があります。syncs_behind
state: READY process: 30 process_behind: 100 num_rounds: 60 hour_col: 2 day_col: 0 oldest_day_col: 0
10分間で10秒ごとに上記のURLを入力してからprocess
合計値を抽出し、process_behind
それを使用して次の条件で検証する必要があります。
process > 8
process_behind = 0
syncが8より大きく、process_behind = 0の場合は、「データ検証済み」というメッセージでシェルスクリプトを終了し、それ以外の場合は10分間続行します。 10分以内に上記の条件が満たされない場合は、シェルスクリプトを終了します。言い換えれば、再試行しません。
以下は、上記のタスクを実行し、サーバーの起動時に通常の状況でうまく機能するシェルスクリプトです。
#!/bin/bash
COUNT=60 #number of 10 second timeouts in 10 minutes
while [[ $COUNT -ge "0" ]]; do
#send the request, put response in variable
DATA=$(wget -O - -q -t 1 http://hostname.domain.com:8080/beat)
#grep $DATA for process and process_behind
PROCESS=$(echo $DATA | grep -oE 'process: [0-9]+' | awk '{print $2}')
PROCESS_BEHIND=$(echo $DATA | grep -oE 'process_behind: [0-9]+' | awk '{print $2}')
echo $PROCESS
echo $PROCESS_BEHIND
#verify conditionals
if [[ $PROCESS -gt "8" && $PROCESS_BEHIND -eq "0" ]]; then exit 0; fi
#decrement the counter
let COUNT-=1
#wait another 10 seconds
sleep 10
done
サーバーがダウンしているとエラーが発生し、その行でwget
例外が発生したとします。
今やりたいことは、サーバーがダウンしている場合は30秒間スリープモードを維持し、サーバーURLの実行を再試行し、失敗した場合は30秒間スリープモードに戻してサーバーURLの実行を再試行することです。 nが10であるとし、サーバーURLをn回実行しましょう。
その後も、サーバーはまだ起動せず、ゼロ以外の状態でシェルスクリプトを終了し、メッセージサーバーがダウンしました。ただし、サーバーが稼働していて応答を受信できる場合は、後でシェルスクリプトからそのフィールドを引き続き抽出します。
Bashシェルスクリプトで再試行メカニズムを実装できますか?それともwget以外に良い方法がありますか?
アップデート 1:-
これが私が得たものです -
#!/bin/bash
COUNT=60 #number of 10 second timeouts in 10 minutes
DATA=""
RETRY=10
while [[ $COUNT -ge "0" ]]; do
while [ $RETRY -gt 0 ]
do
#send the request, put response in variable
DATA=$(wget -O - -q -t 1 http://machineA:8080/beat)
echo "Hello"
if [ $? -eq 0 ]
then
break
else
let RETRY-=1
sleep 30
fi
done
if [ $RETRY -eq 0 ]
then
exit 2
fi
#grep $DATA for process and process_behind
PROCESS=$(echo $DATA | grep -oE 'process: [0-9]+' | awk '{print $2}')
PROCESS_BEHIND=$(echo $DATA | grep -oE 'process_behind: [0-9]+' | awk '{print $2}')
echo $PROCESS
echo $PROCESS_BEHIND
#verify conditionals
if [[ $PROCESS -gt "8" && $PROCESS_BEHIND -eq "0" ]]; then exit 0; fi
#decrement the counter
let COUNT-=1
#wait another 10 seconds
sleep 10
done
サーバーがダウンして上記のシェルスクリプトを実行している場合は、コンソールに「Hello」と印刷され、正常に動作します。しかし、以下の私のアップデートをご覧ください。
アップデート 2:-
さて、今問題を見つけました。このようなシェルスクリプトを実行すると、本番システムで実行され、サーバーがダウンしても「Hello」はまったく印刷されません。しかし、アップデート1で上記のシェルスクリプトを実行しましたが、サーバーがダウンした場合は正常に動作します。
#!/bin/bash
COUNT=60 #number of 10 second timeouts in 10 minutes
HOSTNAME=machineA
DATA=""
RETRY=10
while [[ $COUNT -ge "0" ]]; do
while [ $RETRY -gt 0 ]
do
#send the request, put response in variable
DATA=$(wget -O - -q -t 1 http://$HOSTNAME:8080/beat)
echo "Hello"
if [ $? -eq 0 ]
then
break
else
let RETRY-=1
sleep 30
fi
done
if [ $RETRY -eq 0 ]
then
exit 2
fi
#grep $DATA for process and process_behind
PROCESS=$(echo $DATA | grep -oE 'process: [0-9]+' | awk '{print $2}')
PROCESS_BEHIND=$(echo $DATA | grep -oE 'process_behind: [0-9]+' | awk '{print $2}')
echo $PROCESS
echo $PROCESS_BEHIND
#verify conditionals
if [[ $PROCESS -gt "8" && $PROCESS_BEHIND -eq "0" ]]; then exit 0; fi
#decrement the counter
let COUNT-=1
#wait another 10 seconds
sleep 10
done
上記のスクリプトを使用してデバッグモードで取得した結果は次のとおりです。
david@some-machine:~$ bash -x ./ping1.sh
+ set -e
+ COUNT=60
+ HOSTNAME=machineA
+ DATA=
+ RETRY=10
+ echo machineA
machineA
+ [[ 60 -ge 0 ]]
+ '[' 10 -gt 0 ']'
++ wget -O - -q -t 1 http://machineA:8080/beat
+ DATA=
これらの2つのスクリプトは同じだと思いますか?それでは、なぜこれが起こるのですか?
答え1
簡単なループを使用できます。
....
DATA=""
RETRY=10
while [ "$RETRY" -gt 0 ]; do
DATA="$(wget -O - -q -t 1 http://hostname.domain.com:8080/beat)"
if [ $? -eq 0 ]
then
break
else
let RETRY-=1
sleep 30
fi
done
if [ "$RETRY" -eq 0 ]
then
exit 2
fi
....