【问题标题】:How to implement retry mechanism if the shell script execution got failed?如果shell脚本执行失败,如何实现重试机制?
【发布时间】:2013-12-29 08:18:12
【问题描述】:

我正在尝试在 Python 代码中执行 shell 脚本。到目前为止,一切看起来都很好。

下面是我的 Python 脚本,它将执行一个 shell 脚本。现在举个例子,这里是一个简单的 Hello World shell 脚本。

jsonStr = '{"script":"#!/bin/bash\\necho Hello world 1\\n"}'
j = json.loads(jsonStr)

shell_script = j['script']

print "start"
proc = subprocess.Popen(shell_script, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(stdout, stderr) = proc.communicate()
if stderr:
   print "Shell script gave some error"
   print stderr
else:
   print stdout
   print "end" # Shell script ran fine.

现在我正在寻找的是,假设无论出于何种原因,每当我从 Python 代码执行我的 shell 脚本时,无论出于何种原因它都失败了。那么这意味着stderr 不会为空。所以现在我想再次重试执行 shell 脚本,假设在休眠几毫秒后?

意思是如果shell脚本执行失败,是否有可能实现重试机制?我可以重试 5 或 6 次吗?意思是这个号码也可以配置吗?

【问题讨论】:

    标签: python bash shell subprocess


    【解决方案1】:
    from time import sleep
    MAX_TRIES = 6
    
    # ... your other code ...
    
    for i in xrange(MAX_TRIES):
        proc = subprocess.Popen(shell_script, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (stdout, stderr) = proc.communicate()
        if stderr:
           print "Shell script gave some error..."
           print stderr
           sleep(0.05) # delay for 50 ms
        else:
           print stdout
           print "end" # Shell script ran fine.
           break
    

    【讨论】:

    • for TRY in xrange?这在语法上正确吗?我希望SyntaxError: invalid syntax
    • 当您想要一个描述性的变量名称并遇到此问题时,attempt 是“尝试”的一个很好的同义词;)
    • @KarlKnechtel -- 是的! :-) 实际上,如果我是为自己编写的,我会使用 _ 作为迭代器变量,因为它通常用作一次性/未使用的名称,但我认为如果 OP 不是,这可能会使事情更加混乱熟悉。
    • 显然有些人不喜欢 _ 用于此目的,因为一些替代 REPL(例如 IronPython,IIRC 提供的那个)赋予它特殊含义(它存储前一个表达式的值) .但IMO这个反对意见是相当愚蠢的。 :)
    【解决方案2】:

    可能是这样的:

    maxRetries = 6
    retries = 0
    
    while (retries < maxRetries):
        doSomething ()
        if errorCondition:
            retries += 1
            continue
        break
    

    【讨论】:

    • 感谢您的建议。但是我如何将它与我当前的代码集成呢?就像在我的 python 脚本中一样,我正在执行一个 shell 脚本,如果它因任何原因失败,我想重试。
    • 如果你的代码不是cargo-cult,你应该可以很容易地集成它。 doSomething 是您的子流程调用,errorCondition 是您问题中指定的错误条件。
    【解决方案3】:

    使用装饰器怎么样?似乎是一个非常明确的方法。 您可以在https://wiki.python.org/moin/PythonDecoratorLibrary 阅读有关它们的信息。 (重试装饰器)

    【讨论】:

      最近更新 更多