我想在 shell 脚本中编写逻辑,如果由于某些问题而失败,它将根据“状态代码 = FAIL”在 15 秒后重试运行最多 5 次。
Ale*_*der 189
for i in 1 2 3 4 5; do command && break || sleep 15; done
Run Code Online (Sandbox Code Playgroud)
用您的命令替换“命令”。这是假设“状态代码=失败”意味着任何非零返回代码。
使用{..}语法。适用于大多数 shell,但不适用于 BusyBox sh:
for i in {1..5}; do command && break || sleep 15; done
Run Code Online (Sandbox Code Playgroud)
使用seq并传递失败命令的退出代码:
for i in $(seq 1 5); do command && s=0 && break || s=$? && sleep 15; done; (exit $s)
Run Code Online (Sandbox Code Playgroud)
同上,但sleep 15在最终失败后跳过。由于最好只定义一次最大循环数,这是通过在循环开始时休眠来实现的,如果i > 1:
for i in $(seq 1 5); do [ $i -gt 1 ] && sleep 15; command && s=0 && break || s=$?; done; (exit $s)
Run Code Online (Sandbox Code Playgroud)
sus*_*tus 151
此脚本使用计数器n将命令的尝试次数限制为五次。如果命令成功,$?将保持为零并且执行将从循环中中断。
n=0
until [ "$n" -ge 5 ]
do
command && break # substitute your command here
n=$((n+1))
sleep 15
done
Run Code Online (Sandbox Code Playgroud)
Fer*_*eia 48
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
}
Run Code Online (Sandbox Code Playgroud)
例子:
retry ping invalidserver
Run Code Online (Sandbox Code Playgroud)
产生这个输出:
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
Run Code Online (Sandbox Code Playgroud)
有关具有复杂命令的真实工作示例,请参阅此脚本。
Ole*_*nge 19
GNU Parallel 具有--retries:
parallel --retries 5 --delay 15s ::: ./do_thing.sh
Run Code Online (Sandbox Code Playgroud)
例子:
parallel -t --retries 5 --delay 0.1s 'echo {};exit {}' ::: {0..10}
Run Code Online (Sandbox Code Playgroud)
Rah*_*til 12
这是重试的功能
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 $*
Run Code Online (Sandbox Code Playgroud)
输出 :
[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 ::
Run Code Online (Sandbox Code Playgroud)
小智 12
这是我最喜欢的一行别名/脚本
alias retry='while [ $? -ne 0 ] ; do fc -s ; done'
Run Code Online (Sandbox Code Playgroud)
然后你可以做这样的事情:
$ ps -ef | grep "Next Process"
$ retry
Run Code Online (Sandbox Code Playgroud)
它将继续运行先前的命令,直到找到“下一个进程”
Gra*_*ett 10
由于需要多次执行此操作,脚本变得失控,因此我为此创建了一个专用工具,称为重试。
retry --until=success --times=5 --delay=15 command ...
Run Code Online (Sandbox Code Playgroud)
如果您需要多个命令,您可以使用sh -c,例如
retry -- sh -c 'date && false'
Run Code Online (Sandbox Code Playgroud)
可以在这里重试: https: //github.com/minfrin/retry
小智 5
我使用这个脚本来重试给定的命令,这个脚本的好处是,如果所有重试都失败,它将保留退出代码。
#!/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
Run Code Online (Sandbox Code Playgroud)
也许它可以变得更简单
小智 5
您可以使用此处loop提供的命令,如下所示:
$ loop './do_thing.sh' --every 15s --until-success --num 5
Run Code Online (Sandbox Code Playgroud)
它将每 15 秒执行一次您的操作,直到成功为止,最多执行 5 次。