94

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

例如:

$ 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.
4

7 回答 7

147

文档

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

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

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
于 2010-10-06T22:14:53.307 回答
31

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

from fabric.api import sudo, warn_only

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

更新:我使用以下代码再次确认这在 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')
于 2013-10-23T15:30:33.363 回答
13

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

def local():
    env.warn_only = True
于 2011-11-09T20:21:38.903 回答
11

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

例如:

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.

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

于 2015-01-16T18:15:31.717 回答
8

Fabric 2.x中,您可以使用带有warn=True参数的invoke运行。无论如何,invokeFabric 2.x的依赖项:

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

从任务中:

from invoke import task

@task
def my_task(c):
    c.run('bad command', warn=True)
于 2018-06-20T08:37:00.420 回答
7

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

于 2011-12-01T19:13:24.077 回答
-5

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

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

env.skip_bad_hosts = True

或传递--skip-bad-hosts标志/

于 2016-09-19T14:25:33.687 回答