Fabric bir hata aldığında göreve devam etme


94

Birkaç uzak sunucuda çalışacak bir görev tanımladığımda, görev birinci sunucuda çalışıyorsa ve bir hatayla çıkıyorsa, Fabric görevi durduracak ve iptal edecek. Ancak kumaşın hatayı görmezden gelmesini ve görevi sonraki sunucuda çalıştırmasını istiyorum. Bunu nasıl yaptırabilirim?

Örneğin:

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

Yanıtlar:


146

Gönderen docs :

... Fabric varsayılan olarak "hızlı hata" davranış modeline sahiptir: sıfır olmayan bir dönüş değeri döndüren uzak bir program veya fabfile'nizin Python kodunun bir istisna ile karşılaşması gibi bir şey ters giderse, yürütme hemen durur.

Bu tipik olarak istenen davranıştır, ancak kuralın birçok istisnası vardır, bu nedenle Fabric env.warn_only bir Boole ayarı sağlar. Varsayılan olarak False, yani bir hata koşulunun programın derhal iptal edilmesine neden olacağı anlamına gelir. Bununla birlikte, eğer env.warn_only hata anında True olarak ayarlanırsa - diyelim, ayarlar bağlam yöneticisi ile - Fabric bir uyarı mesajı verir ancak çalışmaya devam eder.

Eğer hatalar kullanılarak göz ardı nerede üzerinde ince taneli kontrol uygular gibi görünüyor settingsbağlam yöneticisi şöyle bir şey:

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
İthal etmeyi unutmayınfrom fabric.api settings
cevaris

31

Fabric 1.5'ten itibaren, bunu kolaylaştıran bir ContextManager var:

from fabric.api import sudo, warn_only

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

Güncelleme: Bunun ipython'da aşağıdaki kodu kullanarak çalıştığını yeniden onayladım.

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

Hangi kumaş versiyonunu kullanıyorsunuz? Fabric == 1.6.2 ile yeniden test ettim ve sorunsuz çalışıyor.
Chris Marinos

Muhtemelen Fabric == 1.9.0 kullanıyorum ve benim için çalışmıyor
cevaris

1.9.0'da da test edildi. Güncellenen yorumumdaki örnek kodu denediğinizde çıktınız nedir?
Chris Marinos

Uyarıları / hataları yazdırmak istemiyorsanız, içerik gizleme yöneticisini de kullanabilirsiniz :with hide('everything'):
np8

13

Ayrıca tüm komut dosyasının warn_only ayarını true olarak da ayarlayabilirsiniz.

def local():
    env.warn_only = True

10

abort_exceptionOrtam değişkenini ayarlamalı ve istisnayı yakalamalısınız.

Örneğin:

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.

Ayrıca bir bloğa da ayarlayabilirsiniz. Buradaki belgelere bakın .


Bunun için teşekkürler, ancak bir soru - mevcut kumaş ortamına istisna meydana geldiğinde tanımlandığı gibi erişim / geçiş mümkün müdür? (Böylece istisna dışında bazı özel ayarları yazdırabilirim.)
Brian

@Brian: Sadece kontrol edilemedi fabric.api.envsizin içinde exceptbloğun?
ArtOfWarfare

@ArtOfWarefare Ahh aptal ben, tüm görevlerimi bir denemede / dışında sarmadan kaçınmaya çalışıyordum ve bunun yerine sadece env.abort_exception=MyExceptionkendi başarısızlığımı çalıştırabilmem için ayarladım . Bir sınıf yerine bir işlev kullanırsam bir çeşit "işe yarıyor" (çağrılabilir gereksinimi karşılar abort_exception) ama yine de bu yaklaşımla ilgili diğer bazı sorunlar üzerinde çalışıyorum.
Brian

@Brian: Bu işlevin gövdesinin içinde ne fabric.api.envolduğunu kontrol edin .
ArtOfWarfare

7

En azından Fabric 1.3.2'de istisnayı yakalayarak istisnayı kurtarabilirsiniz SystemExit. Bir toplu işte (bir dağıtım gibi) çalıştırmak için birden fazla komutunuz varsa ve bunlardan biri başarısız olursa temizlemek istiyorsanız bu yararlıdır.


+1: Test edildi - bu aynı zamanda Fabric 1.9.0'da da çalışır. Bunu yakaladıktan sonra, SystemExitdaha fazla ayrıntı için mesajını veya kodunu kontrol edebilirsiniz .
ArtOfWarfare

Yakalamaktan bile daha iyi SystemExit, abort_exceptionfarklı bir istisnaya ayarlayın, böylece Fabric ile hiçbir ilgisi olmayan istisnaları yanlışlıkla yakalamayın. Bir örnek için
cevabıma

7

In Fabric 2.x sadece kullanabilirsiniz çağırmak 'ın run ile = uyarmak Gerçek argüman. Her neyse, invoke Fabric 2.x'in bir bağımlılığıdır :

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

Bir görevin içinden:

from invoke import task

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

-5

Benim durumumda, Fabric> = 1.4'te bu cevap doğru cevaptı .

Bunu ekleyerek kötü ana bilgisayarları atlayabilirsiniz:

env.skip_bad_hosts = True

Veya --skip-bad-hostsbayrağı uzatmak /

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.