Cách tiếp tục tác vụ khi Vải gặp lỗi


94

Khi tôi xác định một tác vụ để chạy trên một số máy chủ từ xa, nếu tác vụ chạy trên một máy chủ và thoát ra với lỗi, Fabric sẽ dừng và hủy bỏ tác vụ. Nhưng tôi muốn làm cho vải bỏ qua lỗi và chạy tác vụ trên máy chủ tiếp theo. Làm thế nào tôi có thể làm cho nó làm điều này?

Ví dụ:

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

Câu trả lời:


146

Từ các tài liệu :

... Fabric mặc định ở dạng hành vi "fail-fast": nếu có bất kỳ sự cố nào, chẳng hạn như chương trình từ xa trả về giá trị trả về khác không hoặc mã Python của fabfile của bạn gặp phải ngoại lệ, việc thực thi sẽ tạm dừng ngay lập tức.

Đây thường là hành vi mong muốn, nhưng có nhiều ngoại lệ đối với quy tắc, vì vậy, Fabric cung cấp env.warn_only, một cài đặt Boolean. Nó mặc định là False, có nghĩa là một điều kiện lỗi sẽ dẫn đến việc chương trình bị hủy bỏ ngay lập tức. Tuy nhiên, nếu env.warn_only được đặt thành True tại thời điểm không thành công - với, chẳng hạn, trình quản lý ngữ cảnh cài đặt - Fabric sẽ phát ra thông báo cảnh báo nhưng vẫn tiếp tục thực thi.

Có vẻ như bạn có thể thực hiện quyền kiểm soát chi tiết đối với vị trí các lỗi được bỏ qua bằng cách sử dụng trình settingsquản lý ngữ cảnh , tương tự như vậy:

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
Đừng quên nhậpfrom fabric.api settings
cevaris

31

Kể từ Fabric 1.5, có ContextManager giúp việc này dễ dàng hơn:

from fabric.api import sudo, warn_only

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

Cập nhật: Tôi đã xác nhận lại rằng điều này hoạt động trong ipython bằng cách sử dụng mã sau.

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

Bạn đang sử dụng phiên bản vải nào? Tôi vừa thử nghiệm lại với Fabric == 1.6.2 và nó hoạt động tốt.
Chris Marinos

Có lẽ, tôi đang sử dụng vải == 1.9.0 và nó không làm việc cho tôi
cevaris

Cũng vừa thử nghiệm trên 1.9.0. Đầu ra của bạn là gì khi bạn thử mã ví dụ từ nhận xét cập nhật của tôi?
Chris Marinos

Nếu bạn không muốn in những lời cảnh báo / lỗi, bạn cũng có thể sử dụng hide quản lý bối cảnh:with hide('everything'):
np8

13

Bạn cũng có thể đặt toàn bộ cài đặt warning_only của tập lệnh thành true với

def local():
    env.warn_only = True

10

Bạn nên đặt abort_exception biến môi trường và bắt ngoại lệ.

Ví dụ:

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.

Bạn cũng có thể đặt nó trong một khối với. Xem tài liệu tại đây .


Cảm ơn vì điều này, nhưng một câu hỏi - có thể truy cập / chuyển trong kết cấu hiện tại env dict như được xác định khi ngoại lệ xảy ra không? (Vì vậy, tôi có thể in một số cài đặt cụ thể với ngoại lệ.)
Brian

@Brian: Bạn không thể chỉ kiểm tra fabric.api.envtrong exceptkhối của bạn ?
ArtOfWarfare

@ArtOfWarefare Ahh ngớ ngẩn tôi đã cố gắng tránh gói tất cả các nhiệm vụ của mình trong một lần thử / ngoại trừ và thay vào đó chỉ thiết lập env.abort_exception=MyExceptionđể tôi có thể tự chạy thất bại. Nó đại loại là "hoạt động" nếu tôi sử dụng một hàm thay vì một lớp (đáp ứng yêu cầu có thể gọi cho abort_exception) nhưng tôi vẫn đang giải quyết một số vấn đề khác với cách tiếp cận đó.
Brian

@Brian: Vì vậy, bên trong phần thân của chức năng đó, hãy kiểm tra xem fabric.api.envlà gì .
ArtOfWarfare

7

Ít nhất trong Fabric 1.3.2, bạn có thể khôi phục ngoại lệ bằng cách bắt SystemExitngoại lệ. Điều đó rất hữu ích nếu bạn có nhiều lệnh chạy trong một đợt (như triển khai) và muốn dọn dẹp nếu một trong số chúng không thành công.


+1: Đã thử nghiệm - điều này cũng hoạt động trong Vải 1.9.0. Sau khi nắm bắt được điều này, bạn có thể kiểm tra SystemExittin nhắn hoặc mã của để biết thêm chi tiết.
ArtOfWarfare

Thậm chí tốt hơn là bắt SystemExit, hãy đặt abort_exceptionthành một ngoại lệ khác để bạn không vô tình bắt được các ngoại lệ không liên quan gì đến Vải. Xem câu trả lời của tôi để làm ví dụ: stackoverflow.com/a/27990242/901641
ArtOfWarfare,

7

Trong Vải 2.x bạn chỉ có thể sử dụng invoke 's chạy với cảnh báo = True đối số. Dù sao thì, gọi là phụ thuộc của Fabric 2.x :

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

Từ bên trong một nhiệm vụ:

from invoke import task

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

-5

Trong trường hợp của tôi, trên Fabric> = 1,4 câu trả lời này là đúng.

Bạn có thể bỏ qua các máy chủ không hợp lệ bằng cách thêm cái này:

env.skip_bad_hosts = True

Hoặc vượt qua --skip-bad-hostslá cờ /

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.