如何在Bash中重试命令?

时间:2011-09-16 20:00:46

标签: bash

我有一个执行时间不到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中执行此操作?

8 个答案:

答案 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也可以使用,并允许其他后台作业。您可能需要尝试使用killwait,具体取决于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函数,除非它们已被移动到另一个脚本中,然后通过重试调用)。

retrycli

pip install git+git://github.com/sky-shiny/retrycli.git
retry my_command