ファブリックがエラーを受け取ったときにタスクを続行する方法


94

複数のリモートサーバーで実行するタスクを定義すると、タスクがサーバー1で実行されてエラーで終了すると、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.

回答:


146

ドキュメントから:

...ファブリックのデフォルトは「フェイルファスト」動作パターンです。ゼロ以外の戻り値を返すリモートプログラムや、例外が発生した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

13
インポートすることを忘れないでくださいfrom fabric.api settings
cevaris

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')

どのバージョンのファブリックを使用していますか?私は、Fabric == 1.6.2で再テストしたところ、問題なく動作しました。
Chris Marinos

多分、私はFabric == 1.9.0を使用していて、それは私にとっては
うまくいき

1.9.0でもテストしました。更新されたコメントのコード例を試したときの出力は何ですか?
Chris Marinos、

あなたは警告/エラーを印刷しない場合は、使用することができます非表示:コンテキストマネージャwith hide('everything'):
NP8

13

また、スクリプト全体のwarn_only設定をtrueに設定することもできます。

def local():
    env.warn_only = True

10

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ブロックで設定することもできます。こちらのドキュメントをご覧ください


これをありがとう、しかし1つの質問-例外が発生したときに定義された現在のファブリック環境辞書でアクセス/パスすることは可能ですか?(そのため、例外を除いていくつかの特定の設定を印刷できます。)
Brian

@ブライアン:fabric.api.envあなたはあなたのexceptブロック内をチェックできませんでしたか?
ArtOfWarfare 2015

@ArtOfWarefareああ、ばかげた私は、try / exceptですべてのタスクをラップするのを避け、代わりにenv.abort_exception=MyException自分の失敗を実行できるようにセットアップするだけでした。クラスの代わりに関数を使用すると(「の呼び出し可能要求」を満たします)、「動作」するように見えabort_exceptionますが、そのアプローチの他のいくつかの問題にはまだ取り組んでいます。
ブライアン

@ブライアン:その関数の本体の内部を確認してくださいfabric.api.env
ArtOfWarfare 2015

7

少なくともファブリック1.3.2では、例外をキャッチすることで例外を回復できSystemExitます。これは、(デプロイなどの)バッチで実行するコマンドが複数あり、そのうちの1つが失敗した場合にクリーンアップする場合に役立ちます。


+1:テスト済み-これはファブリック1.9.0でも機能します。これをキャッチした後、SystemExit詳細についてのメッセージまたはコードを確認できます。
ArtOfWarfare 14

をキャッチするよりも、別の例外をSystemExit設定abort_exceptionして、Fabricとは関係のない例外を誤ってキャッチしないようにします。例については私の答えを参照してください:stackoverflow.com/a/27990242/901641
ArtOfWarfare

7

生地から2.xあなただけ使用することができます呼び出し実行をして警告= Trueの引数。とにかく、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)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.