我有一个执行时间不到1分钟的命令,但由于某种原因,它有一个非常长的内置超时机制。我想要一些执行以下操作的bash:
success = False
try(my_command)
while(!(success))
wait 1 min
if my command not finished
retry(my_command)
else
success = True
end while
我怎样才能在Bash中执行此操作?
答案 0 :(得分:16)
查看GNU timeout
命令。如果在给定时间内没有完成,则会终止该过程;你只需绕一个循环来等待timeout
成功完成,并在适当的重试之间延迟等等。
while timeout -k 70 60 -- my_command; [ $? = 124 ]
do sleep 2 # Pause before retry
done
如果你必须使用纯bash
(这不可行 - bash
使用许多其他命令),那么你就会陷入信号处理程序和所有人的痛苦和挫败的世界各种各样的问题。
答案 1 :(得分:4)
我找到了一个来自的脚本: http://fahdshariff.blogspot.com/2014/02/retrying-commands-in-shell-scripts.html
import {Component, AfterViewInit, ElementRef} from 'angular2/core';
@Component({})
class Class1 {
name: string;
constructor(private el: ElementRef) {}
private setName() {
this.name = "test";
}
ngAfterViewInit() {
this.setName();
}
}
@Component({
selector: 'test'
})
export class Class2 extends Class1 {
ngAfterViewInit() {
super.ngAfterViewInit();
console.log(this.name);
}
}
答案 2 :(得分:0)
您可以使用&
后台运算符运行命令并保留控制权。在后台运行您的命令sleep
,只要您愿意在前台运行,然后,如果后台作业没有终止,请将其终止并重新开始。
答案 3 :(得分:0)
while true ; do
my_command &
sleep 60
if [[ $(jobs -r) == "" ]] ; then
echo "Job is done"
break
fi
# Job took too long
kill -9 $!
done
答案 4 :(得分:0)
调整@ Shin的答案以使用kill -0
而不是jobs
,这样即使使用经典的Bourne shell也可以使用,并允许其他后台作业。您可能需要尝试使用kill
和wait
,具体取决于my_command
对这些内容的响应方式。
while true ; do
my_command &
sleep 60
if kill -0 $! 2>/dev/null; then
# Job took too long
kill $!
else
echo "Job is done"
# Reap exit status
wait $!
break
fi
done
答案 5 :(得分:0)
我喜欢@ Jonathan的回答,但试图让它更直接以备将来使用:
until timeout 1 sleep 2
do
echo "Happening after 1s of sleep"
done
答案 6 :(得分:0)
# Retries a given command given number of times and outputs to given variable
# $1 : Command to be passed : handles both simple, piped commands
# $2 : Final output of the command(if successfull)
# $3 : Number of retrial attempts[Default 5]
function retry_function() {
echo "Command to be executed : $1"
echo "Final output variable : $2"
echo "Total trials [Default:5] : $3"
counter=${3:-5}
local _my_output_=$2 #make sure passed variable is not same as this
i=1
while [ $i -le $counter ]; do
local my_result=$(eval "$1")
# this tests if output variable is populated and accordingly retries,
# Not possible to provide error status/logs(STDIN,STDERR)-owing to subshell execution of command
# if error logs are needed, execute the same code, outside function in same shell
if test -z "$my_result"
then
echo "Trial[$i/$counter]: Execution failed"
else
echo "Trial[$i/$counter]: Successfull execution"
eval $_my_output_="'$my_result'"
break
fi
let i+=1
done
}
retry_function "ping -c 4 google.com | grep \"min/avg/max\" | awk -F\"/\" '{print \$5}'" avg_rtt_time
echo $avg_rtt_time
- To pass in a lengthy command, pass a method echoing the content. Take care of method expansion accordingly in a subshell at appropriate place.
- Wait time can be added too - just before the increment!
- For a complex command, youll have to take care of stringifying it(Good luck)
答案 7 :(得分:-1)
使用" retrycli"你可以在任何bash脚本或工具上获得指数退避和重试的工具(不是bash函数,除非它们已被移动到另一个脚本中,然后通过重试调用)。
pip install git+git://github.com/sky-shiny/retrycli.git
retry my_command