在远程Shell中使用Fabric进行run()调用时,能否捕获错误代码?


69

通常,只要run()调用返回非零退出代码,Fabric就会退出。但是,对于某些电话,这是预期的。例如,当PNGOut无法压缩文件时,它将返回错误代码2。

目前,我只能通过使用shell逻辑(do_something_that_fails || truedo_something_that_fails || do_something_else)来规避此限制,但我希望能够将逻辑保留在纯Python中(Fabric承诺)。

有没有一种方法可以检查错误代码并对错误代码做出反应,而不是让Fabric死机而死?我仍然希望其他呼叫具有默认行为,因此通过修改环境来更改其行为似乎不是一个好选择(据我所知,您只能使用它来警告它而不是死亡)。


2
在有人将其标记为重复之前:这个问题是相关的,但是正如我所说,我想对错误做出反应,而不是忽略它们。
艾伦·李

当前接受的答案已过时。自2013年7月以来,有一个环境变量可让您指定发生错误时应引发哪个异常(默认值为SystemExit,这不是Exception的后代,这通常是导致程序崩溃的原因)。见我的答案:stackoverflow.com/a/25293275/901641
ArtOfWarfare 2014年

//,我很好奇Invoke如何处理此问题。
内森·巴桑内塞

Answers:


94

您可以通过使用settings上下文管理器和以下warn_only设置来防止中止非零退出代码:

from fabric.api import settings

with settings(warn_only=True):
    result = run('pngout old.png new.png')
    if result.return_code == 0: 
        do something
    elif result.return_code == 2: 
        do something else 
    else: #print error to user
        print result
        raise SystemExit()

更新:我的答案已经过时。请参阅下面的评论。


2
您甚至不需要检查return_code,result的值根据任务的成功状态评估为布尔值true或false。docs.fabfile.org/en/1.7/api/core/…–
Fraser Graham

2
这对于超时错误不起作用。使用或不使用“使用设置”,甚至尝试/除外,Fabric仍然完全退出。
塞林2014年

-1:这个答案是过时的-自2013年7月以来,可以指定在调用错误时调用哪个异常。在这里查看我的答案:stackoverflow.com/a/25293275/901641
ArtOfWarfare 2014年

我修复了Python缩进,但是现在我无法删除为使修改生效而添加的多余文本。
克里斯蒂安·朗

2
您还可以使用result.succeededresult.failed。当心直接评估,bool(result)因为它使用输出,因此与之结合使用hide("warnings"),将无法从失败中判断成功。
重写

29

是的你可以。只需更改环境的即可abort_exception。例如:

from fabric.api import settings

class FabricException(Exception):
    pass

with settings(abort_exception = FabricException):
    try:
        run(<something that might fail>)
    except FabricException:
        <handle the exception>

在该文档abort_exception在这里


1
但是,这似乎无法提供对命令退出代码的访问。
艾伦·梅

@AlanPlum-您可以获取异常消息...但是您是对的,我看不到获取退出代码的方法。
ArtOfWarfare

4

与环境显然搞乱答案。

fabric.api.settings可以用作上下文管理器(带有with)将其应用于单个语句。的返回值run()local()sudo()电话是不是shell命令只是输出,还具有特殊性能(return_codefailed),允许反应的错误。

我想我正在寻找更接近subprocess.PopenPython通常的异常处理行为的东西。


2

尝试这个

from fabric.api import run, env
env.warn_only = True # if you want to ignore exceptions and handle them yurself

command = "your command"
x = run(command, capture=True) # run or local or sudo
if(x.stderr != ""):
    error = "On %s: %s" %(command, x.stderr)
    print error
    print x.return_code # which may be 1 or 2
    # do what you want or
    raise Exception(error) #optional
else:
    print "the output of %s is: %s" %(command, x)
    print x.return_code # which is 0

3
我用以下结果尝试了上述方法:TypeError: run() got an unexpected keyword argument 'capture'Fabric 1.10.2和Paramiko 1.15.2。
dmmfll

capture=True仅适用于local(command, capture=True)
Kurohige
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.