Tôi muốn viết logic trong shell script sẽ thử lại để chạy lại sau 15 giây tối đa 5 lần dựa trên "mã trạng thái = FAIL" nếu nó không thành công do một số vấn đề.
Tôi muốn viết logic trong shell script sẽ thử lại để chạy lại sau 15 giây tối đa 5 lần dựa trên "mã trạng thái = FAIL" nếu nó không thành công do một số vấn đề.
Câu trả lời:
Kịch bản lệnh này sử dụng một bộ đếm n
để giới hạn các lần thử tại lệnh thành năm. Nếu lệnh thành công, $?
sẽ giữ số 0 và thực thi sẽ thoát khỏi vòng lặp.
n=0
until [ $n -ge 5 ]
do
command && break # substitute your command here
n=$[$n+1]
sleep 15
done
if command; then break; fi
hay ngắn gọn hơncommand && break
n
thất bại, nó không cần ngủ thêm một lần nữa trước khi thoát ra.
for i in 1 2 3 4 5; do command && break || sleep 15; done
Thay thế "lệnh" bằng lệnh của bạn. Điều này giả định rằng "mã trạng thái = FAIL" có nghĩa là bất kỳ mã trả về khác không.
Sử dụng {..}
cú pháp. Hoạt động trong hầu hết các shell, nhưng không phải BusyBox sh
:
for i in {1..5}; do command && break || sleep 15; done
Sử dụng seq
và chuyển dọc theo mã thoát của lệnh thất bại:
for i in $(seq 1 5); do command && s=0 && break || s=$? && sleep 15; done; (exit $s)
Tương tự như trên, nhưng bỏ qua sleep 15
sau thất bại cuối cùng. Vì tốt hơn là chỉ xác định số vòng lặp tối đa một lần, điều này đạt được bằng cách ngủ ở đầu vòng lặp nếu 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
với for i in {1..5}
vì nó dễ dàng hơn để duy trì.
command
thất bại.
[[ i -eq 5]]
như một điều kiện HOẶC trước khi ngủ để tránh điều này.
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
}
Thí dụ:
retry ping invalidserver
tạo đầu ra này:
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
Đối với một ví dụ thực tế, làm việc với các lệnh phức tạp, hãy xem tập lệnh này .
Đây là chức năng để thử lại
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 $*
Đầu ra:
[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
Đây là bí danh / kịch bản yêu thích của tôi
alias retry='while [ $? -ne 0 ] ; do fc -s ; done'
Sau đó, bạn có thể làm những thứ như:
$ ps -ef | grep "Next Process"
$ retry
và nó sẽ tiếp tục chạy lệnh trước cho đến khi tìm thấy "Quá trình tiếp theo"
fc -e "#"
thay vì fc -s
.
Tôi sử dụng tập lệnh này để thực hiện thử lại một lệnh đã cho, lợi ích của tập lệnh này là nếu thất bại tất cả các lần thử lại, nó sẽ giữ nguyên mã thoát.
#!/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
Có lẽ nó có thể đơn giản hơn
Xem ví dụ dưới đây:
n=0
while :
do
nc -vzw1 localhost 3859
[[ $? = 0 ]] && break || ((n++))
(( n >= 5 )) && break
done
Tôi đang cố gắng kết nối cổng 3389 trên localhost, nó sẽ thử lại cho đến khi thất bại 5 lần, nếu thành công thì nó sẽ phá vỡ vòng lặp.
$?
Nó tồn tại trạng thái của lệnh nếu nó không có nghĩa là lệnh chạy thành công, nếu khác không có nghĩa là lệnh fai
Có vẻ hơi phức tạp, có thể ai đó làm điều đó tốt hơn thế này.
$?
Nó tồn tại trạng thái của lệnh nếu nó bằng 0 có nghĩa là lệnh chạy thành công, nếu khác không có nghĩa là lệnh thất bại
Bạn có thể sử dụng loop
lệnh, có sẵn ở đây , như vậy:
$ loop './do_thing.sh' --every 15s --until-success --num 5
Điều này sẽ làm việc của bạn cứ sau 15 giây cho đến khi thành công, tối đa năm lần.
Đây là một retry
hàm đệ quy cho những người theo chủ nghĩa lập trình chức năng:
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
}
Truyền cho nó một lệnh (hoặc tên hàm) và tùy chọn một số lần thử lại và thời gian ngủ giữa các lần thử lại, như vậy:
retry some_command_or_fn 5 15 # 5 tries, sleep 15 seconds between each
break
nếu lệnh thành công thì nó sẽ phá vỡ vòng lặp