Fabric이 오류를 수신 할 때 작업을 계속하는 방법


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

에서 워드 프로세서 :

... Fabric은 기본적으로 "fail-fast"동작 패턴을 사용합니다. 원격 프로그램이 0이 아닌 반환 값을 반환하거나 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 2007

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 2014

아마도 나는 Fabric == 1.9.0을 사용하고 있는데 그것은 나를 위해 작동하지 않습니다
cevaris

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 블록에서 설정할 수도 있습니다. 여기 에서 설명서를 참조 하십시오 .


감사합니다.하지만 한 가지 질문이 있습니다. 예외가 발생했을 때 정의 된대로 현재 패브릭 환경에서 액세스 / 전달이 가능한가요? (예외를 제외하고 특정 설정을 인쇄 할 수 있습니다.)
Brian

@Brian : 블록 fabric.api.env내부를 확인하면 안 except되나요?
ArtOfWarfare 2015

@ArtOfWarefare Ahh 어리석은 날 모든 작업을 시도 / 예외로 포장하지 않으려 고 노력하고 대신 env.abort_exception=MyException실패를 실행할 수 있도록 설정했습니다 . 클래스 대신 함수를 사용하면 일종의 "작동" abort_exception이지만 (에 대한 호출 가능한 요구 사항을 충족 함 ) 여전히 해당 접근 방식으로 다른 문제를 해결하고 있습니다.
Brian

@Brian : 그래서 그 함수의 본문 안에 무엇이 있는지 확인하십시오 fabric.api.env.
ArtOfWarfare

7

Fabric 1.3.2 이상에서는 예외를 포착하여 SystemExit예외를 복구 할 수 있습니다 . 이는 배치 (예 : 배포)에서 실행할 명령이 두 개 이상 있고 그중 하나가 실패 할 경우 정리하려는 경우 유용합니다.


+1 : 테스트 됨-Fabric 1.9.0에서도 작동합니다. 이것을 잡은 후의 SystemExit메시지 또는 코드를 확인하여 자세한 내용을 확인할 수 있습니다 .
ArtOfWarfare 2014 년

잡는 것보다 더 좋은 것은 다른 예외로 SystemExit설정 abort_exception하여 Fabric과 관련이없는 예외를 실수로 잡는 일이 없도록합니다. 예를 들어 내 대답을 참조하십시오 : stackoverflow.com/a/27990242/901641
ArtOfWarfare

7

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)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.