मैं शेल स्क्रिप्ट में तर्क लिखना चाहता हूं जो "स्टेटस कोड = फेल " के आधार पर 5 सेकंड तक 15 सेकंड के बाद फिर से चलाने के लिए इसे फिर से चलाएगा यदि यह किसी मुद्दे के कारण विफल हो जाता है।
मैं शेल स्क्रिप्ट में तर्क लिखना चाहता हूं जो "स्टेटस कोड = फेल " के आधार पर 5 सेकंड तक 15 सेकंड के बाद फिर से चलाने के लिए इसे फिर से चलाएगा यदि यह किसी मुद्दे के कारण विफल हो जाता है।
जवाबों:
यह स्क्रिप्ट n
कमांड पर प्रयासों को पाँच तक सीमित करने के लिए एक काउंटर का उपयोग करती है। यदि कमांड सफल होता है, $?
तो शून्य पकड़ लेगा और निष्पादन लूप से टूट जाएगा।
n=0
until [ $n -ge 5 ]
do
command && break # substitute your command here
n=$[$n+1]
sleep 15
done
if command; then break; fi
या अधिक command && break
n
विफलताओं के मामले में , यह अनावश्यक रूप से बाहर निकलने से पहले एक अतिरिक्त समय सोता है।
for i in 1 2 3 4 5; do command && break || sleep 15; done
"कमांड" को अपनी कमांड से बदलें। यह मानकर चल रहा है कि "स्थिति कोड = विफल" का अर्थ किसी भी गैर-शून्य रिटर्न कोड से है।
{..}
वाक्य रचना का उपयोग करना । अधिकांश गोले में काम करता है, लेकिन बिजीबॉक्स नहीं sh
:
for i in {1..5}; do command && break || sleep 15; done
seq
असफल कमांड के निकास कोड का उपयोग करना और पास करना :
for i in $(seq 1 5); do command && s=0 && break || s=$? && sleep 15; done; (exit $s)
ऊपर के समान, लेकिन sleep 15
अंतिम असफल होने के बाद लंघन । चूंकि केवल लूप की अधिकतम संख्या को एक बार परिभाषित करना बेहतर है, यह लूप की शुरुआत में सोने से प्राप्त होता है यदि i > 1
:
for i in $(seq 1 5); do [ $i -gt 1 ] && sleep 15; command && s=0 && break || s=$?; done; (exit $s)
for i in 1 2 3 4 5
साथ for i in {1..5}
है क्योंकि यह बनाए रखने के लिए आसान है।
&&
इससे पहले मूल्यांकन किया जाता है ||
की वजह से ऑपरेटर पूर्वता
command
विफल हो।
[[ i -eq 5]]
इससे बचने के लिए आप सोने से पहले एक OR स्थिति के रूप में चेक लगा सकते हैं ।
function fail {
echo $1 >&2
exit 1
}
function retry {
local n=1
local max=5
local delay=15
while true; do
"$@" && break || {
if [[ $n -lt $max ]]; then
((n++))
echo "Command failed. Attempt $n/$max:"
sleep $delay;
else
fail "The command has failed after $n attempts."
fi
}
done
}
उदाहरण:
retry ping invalidserver
इस उत्पादन का उत्पादन:
ping: unknown host invalidserver
Command failed. Attempt 2/5:
ping: unknown host invalidserver
Command failed. Attempt 3/5:
ping: unknown host invalidserver
Command failed. Attempt 4/5:
ping: unknown host invalidserver
Command failed. Attempt 5/5:
ping: unknown host invalidserver
The command 'ping invalidserver' failed after 5 attempts
एक वास्तविक दुनिया के लिए, जटिल आदेशों के साथ काम करने का उदाहरण, इस स्क्रिप्ट को देखें ।
यहाँ पुनः प्रयास के लिए कार्य किया गया है
function retry()
{
local n=0
local try=$1
local cmd="${@: 2}"
[[ $# -le 1 ]] && {
echo "Usage $0 <retry_number> <Command>"; }
until [[ $n -ge $try ]]
do
$cmd && break || {
echo "Command Fail.."
((n++))
echo "retry $n ::"
sleep 1;
}
done
}
retry $*
आउटपुट:
[test@Nagios ~]$ ./retry.sh 3 ping -c1 localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.207 ms
--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.207/0.207/0.207/0.000 ms
[test@Nagios ~]$ ./retry.sh 3 ping -c1 localhostlasjflasd
ping: unknown host localhostlasjflasd
Command Fail..
retry 1 ::
ping: unknown host localhostlasjflasd
Command Fail..
retry 2 ::
ping: unknown host localhostlasjflasd
Command Fail..
retry 3 ::
bash retry.sh 3 ping -c1 localhost
यहाँ मेरा पसंदीदा एक लाइन उर्फ / स्क्रिप्ट है
alias retry='while [ $? -ne 0 ] ; do fc -s ; done'
फिर आप सामान की तरह कर सकते हैं:
$ ps -ef | grep "Next Process"
$ retry
और जब तक यह "नेक्स्ट प्रोसेस" नहीं मिल जाता, तब तक यह पूर्व कमांड को चालू रखेगा।
fc -e "#"
बजाय का उपयोग करें fc -s
।
मैं इस स्क्रिप्ट का उपयोग करता हूं जो किसी दिए गए कमांड के रिट्रीट को बनाता है, इस स्क्रिप्ट का लाभ यह है कि यदि सभी रिट्स विफल हो जाते हैं तो यह निकास कोड को संरक्षित करेगा।
#!/usr/bin/env bash
if [ $# -ne 3 ]; then
echo 'usage: retry <num retries> <wait retry secs> "<command>"'
exit 1
fi
retries=$1
wait_retry=$2
command=$3
for i in `seq 1 $retries`; do
echo "$command"
$command
ret_value=$?
[ $ret_value -eq 0 ] && break
echo "> failed with $ret_value, waiting to retry..."
sleep $wait_retry
done
exit $ret_value
संभवतः यह सरल हो सकता है
नीचे देखें उदाहरण:
n=0
while :
do
nc -vzw1 localhost 3859
[[ $? = 0 ]] && break || ((n++))
(( n >= 5 )) && break
done
मैं लोकलहोस्ट पर पोर्ट 3389 को जोड़ने की कोशिश कर रहा हूं, यह 5 बार विफल होने तक पीछे हट जाएगा, अगर सफलता मिलती है तो यह लूप तोड़ देगा।
$?
यदि शून्य का अर्थ है, तो कमांड की स्थिति मौजूद है यदि इसका मतलब है कि कमांड सफलतापूर्वक चलता है, यदि शून्य के अलावा अन्य कमांड कमांड का मतलब है
थोड़ा जटिल लगता है, हो सकता है कि कोई इसे इससे बेहतर करे।
$?
यदि यह शून्य का मतलब है कि यह कमांड की स्थिति मौजूद है, तो कमांड सफलतापूर्वक चलता है, यदि शून्य से अन्य का मतलब कमांड फेल है
यहाँ retry
कार्यात्मक प्रोग्रामिंग purists के लिए एक पुनरावर्ती कार्य है:
retry() {
cmd=$1
try=${2:-15} # 15 by default
sleep_time=${3:-3} # 3 seconds by default
# Show help if a command to retry is not specified.
[ -z "$1" ] && echo 'Usage: retry cmd [try=15 sleep_time=3]' && return 1
# The unsuccessful recursion termination condition (if no retries left)
[ $try -lt 1 ] && echo 'All retries failed.' && return 1
# The successful recursion termination condition (if the function succeeded)
$cmd && return 0
echo "Execution of '$cmd' failed."
# Inform that all is not lost if at least one more retry is available.
# $attempts include current try, so tries left is $attempts-1.
if [ $((try-1)) -gt 0 ]; then
echo "There are still $((try-1)) retrie(s) left."
echo "Waiting for $sleep_time seconds..." && sleep $sleep_time
fi
# Recurse
retry $cmd $((try-1)) $sleep_time
}
इसे एक कमांड (या एक फ़ंक्शन नाम) पास करें और वैकल्पिक रूप से कई रिट्रीट और रिट्रीट के बीच एक नींद की अवधि, जैसे:
retry some_command_or_fn 5 15 # 5 tries, sleep 15 seconds between each
break
अगर आदेश सफलताओं तो यह पाश टूट जाएगा