Python Fabric收到错误时如何继续任务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3876936/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 13:08:01  来源:igfitidea点击:

How to continue a task when Fabric receives an error

pythonfabric

提问by Mingo

When I define a task to run on several remote servers, if the task runs on server one and exits with an error, Fabric will stop and abort the task. But I want to make fabric ignore the error and run the task on the next server. How can I make it do this?

当我定义一个在多个远程服务器上运行的任务时,如果该任务在第一台服务器上运行并以错误退出,Fabric 将停止并中止该任务。但我想让fabric 忽略错误并在下一个服务器上运行任务。我怎样才能让它做到这一点?

For example:

例如:

$ fab site1_service_gw
[site1rpt1] Executing task 'site1_service_gw'

[site1fep1] run: echo 'Nm123!@#' | sudo -S route
[site1fep1] err:
[site1fep1] err: We trust you have received the usual lecture from the local System
[site1fep1] err: Administrator. It usually boils down to these three things:
[site1fep1] err:
[site1fep1] err:     #1) Respect the privacy of others.
[site1fep1] err:     #2) Think before you type.
[site1fep1] err:     #3) With great power comes great responsibility.
[site1fep1] err: root's password:
[site1fep1] err: sudo: route: command not found

Fatal error: run() encountered an error (return code 1) while executing 'echo 'Nm123!@#' | sudo -S route '

Aborting.

采纳答案by Will McCutchen

From the docs:

文档

... Fabric defaults to a “fail-fast” behavior pattern: if anything goes wrong, such as a remote program returning a nonzero return value or your fabfile's Python code encountering an exception, execution will halt immediately.

This is typically the desired behavior, but there are many exceptions to the rule, so Fabric provides env.warn_only, a Boolean setting. It defaults to False, meaning an error condition will result in the program aborting immediately. However, if env.warn_only is set to True at the time of failure – with, say, the settings context manager – Fabric will emit a warning message but continue executing.

... Fabric 默认为“快速失败”行为模式:如果出现任何问题,例如远程程序返回非零返回值或您的 fabfile 的 Python 代码遇到异常,执行将立即停止。

这通常是所需的行为,但该规则有许多例外,因此 Fabric 提供了 env.warn_only,一个布尔设置。它默认为 False,意味着错误条件将导致程序立即中止。但是,如果 env.warn_only 在失败时设置为 True - 例如,设置上下文管理器 - Fabric 将发出警告消息但继续执行。

Looks like you can exercise fine-grained control over where errors are ignored by using the settingscontext manager, something like so:

看起来您可以使用settings上下文管理器对忽略错误的位置进行细粒度控制,如下所示:

from fabric.api import settings

sudo('mkdir tmp') # can't fail
with settings(warn_only=True):
    sudo('touch tmp/test') # can fail
sudo('rm tmp') # can't fail

回答by Rawkcy

You can also set the entire script's warn_only setting to be true with

您还可以将整个脚本的 warn_only 设置设置为 true

def local():
    env.warn_only = True

回答by zimbatm

In Fabric 1.3.2 at least, you can recover the exception by catching the SystemExitexception. That's helpful if you have more than one command to run in a batch (like a deploy) and want to cleanup if one of them fails.

至少在 Fabric 1.3.2 中,您可以通过捕获SystemExit异常来恢复异常。如果您有多个命令要在批处理中运行(如部署)并且希望在其中一个失败时进行清理,这将很有帮助。

回答by Chris Marinos

As of Fabric 1.5, there is a ContextManager that makes this easier:

从 Fabric 1.5 开始,有一个 ContextManager 使这更容易:

from fabric.api import sudo, warn_only

with warn_only():
    sudo('mkdir foo')

Update: I re-confirmed that this works in ipython using the following code.

更新:我使用以下代码再次确认这在 ipython 中有效。

from fabric.api import local, warn_only

#aborted with SystemExit after 'bad command'
local('bad command'); local('bad command 2')

#executes both commands, printing errors for each
with warn_only():
    local('bad command'); local('bad command 2')

回答by ArtOfWarfare

You should set the abort_exceptionenvironment variable and catch the exception.

您应该设置abort_exception环境变量并捕获异常。

For example:

例如:

from fabric.api        import env
from fabric.operations import sudo

class FabricException(Exception):
    pass

env.abort_exception = FabricException
# ... set up the rest of the environment...

try:
    sudo('reboot')
except FabricException:
    pass  # This is expected, we can continue.

You can also set it in a with block. See the documentation here.

您也可以将其设置在 with 块中。请参阅此处的文档。

回答by Christian Vielma

In my case, on Fabric >= 1.4 this answerwas the correct one.

就我而言,在 Fabric >= 1.4 上,这个答案是正确的。

You can skip bad hosts by adding this:

您可以通过添加以下内容来跳过坏主机:

env.skip_bad_hosts = True

Or passing the --skip-bad-hostsflag/

或传递--skip-bad-hosts旗帜/

回答by Qlimax

In Fabric 2.xyou can just use invoke's runwith the warn=Trueargument. Anyway, invokeis a dependency of Fabric 2.x:

面料2.X你可以使用调用运行警告=真说法。无论如何,invokeFabric 2.x的依赖项:

from invoke import run
run('bad command', warn=True)

From within a task:

从任务中:

from invoke import task

@task
def my_task(c):
    c.run('bad command', warn=True)