2011-02-03 9 views
63

Normalnie Fabric kończy działanie, gdy wywołanie run() zwraca niezerowy kod wyjścia. W przypadku niektórych połączeń jest to jednak oczekiwane. Na przykład PNGOut zwraca kod błędu 2, gdy nie jest w stanie skompresować pliku.Czy mogę przechwytywać kody błędów podczas korzystania z funkcji Fabric do uruchamiania() w zdalnej powłoce?

Obecnie mogę tylko obejść to ograniczenie przez użycie logiki powłoki (do_something_that_fails || true lub do_something_that_fails || do_something_else), ale wolałbym zachować logikę w zwykłym języku Python (tak jak obietnica Fabric).

Czy istnieje sposób na sprawdzenie kodu błędu i zareagowanie na nie zamiast wywołania paniki i śmierci? Nadal chcę zachowań domyślnych dla innych połączeń, więc zmiana ich zachowania poprzez modyfikację środowiska nie wydaje się dobrym rozwiązaniem (i o ile pamiętam, możesz go użyć, aby ostrzec, zamiast umrzeć w każdym razie).

+2

zanim ktoś wyznacza ten duplikat: [To pytanie jest związane] (http://stackoverflow.com/questions/3876936/how-to-continue-the-task-when- fabric-meet-an-error), ale jak już powiedziałem, chcę je poprawić, a nie ignorować. –

+0

Aktualnie akceptowana odpowiedź jest opatrzona datą. Od lipca 2013 r. Istnieje zmienna środowiskowa, która pozwala określić, który wyjątek powinien zostać podniesiony w przypadku wystąpienia błędu (domyślnie jest to 'SystemExit', który nie jest potomkiem wyjątku, dlatego zazwyczaj powoduje awarię programu). Zobacz moją odpowiedź: http://stackoverflow.com/a/25293275/901641 – ArtOfWarfare

+0

// Ciekaw jestem, jak Invoke sobie z tym poradzi. –

Odpowiedz

87

można zapobiec przerwaniu na niezerowym kodem wyjścia za pomocą menedżera settings kontekst i ustawienie warn_only:

from fabric.api import settings 

with settings(warn_only=True): 
    result = run('pngout old.png new.png') 
    if result.return_code == 0: 
     do something 
    elif result.return_code == 2: 
     do something else 
    else: #print error to user 
     print result 
     raise SystemExit() 

Update: Moja odpowiedź jest przestarzała. Zobacz komentarze poniżej.

+0

Nie trzeba nawet sprawdzać kodu powrotu, wartość wyniku jest określana jako wartość logiczna prawda lub fałsz, w zależności od stanu powodzenia zadania.http: //docs.fabfile.org/en/1.7/api/core/operations .html # fabric.operations.run –

+1

To nie działa w przypadku błędów przekroczenia limitu czasu. Z lub bez "z ustawieniami" lub nawet z try/except, Fabric nadal kończy się całkowicie. – Cerin

+0

-1: Ta odpowiedź jest datowana - od lipca 2013 r. Można określić, który wyjątek zostanie wywołany po wywołaniu błędu. Zobacz moją odpowiedź tutaj: http: // stackoverflow.com/a/25293275/901641 – ArtOfWarfare

4

Najwyraźniej mieszanie się z otoczeniem to odpowiedź.

fabric.api.settings może być użyty jako menedżer kontekstu (z with) do zastosowania go do pojedynczych wyciągów. Wartość zwracana wywołań run(), local() i sudo() nie jest jedynie wynikiem polecenia powłoki, ale ma również specjalne właściwości (return_code i failed), które umożliwiają reagowanie na błędy.

Podejrzewam, że szukałem czegoś bliższego zachowaniu subprocess.Popen lub zwykłej obsłudze wyjątków Pythona.

28

Tak, możesz. Wystarczy zmienić środowisko abort_exception. Na przykład:

from fabric.api import settings 

class FabricException(Exception): 
    pass 

with settings(abort_exception = FabricException): 
    try: 
     run(<something that might fail>) 
    except FabricException: 
     <handle the exception> 

Dokumentacja na abort_exception jest here.

+1

To wydaje się nie zapewniać dostępu do kodu wyjścia polecenia. –

+0

@AlanPlum - Możesz otrzymać komunikat o wyjątku ... ale masz rację, nie widzę sposobu na uzyskanie kodu wyjścia. – ArtOfWarfare

1

spróbować

from fabric.api import run, env 
env.warn_only = True # if you want to ignore exceptions and handle them yurself 

command = "your command" 
x = run(command, capture=True) # run or local or sudo 
if(x.stderr != ""): 
    error = "On %s: %s" %(command, x.stderr) 
    print error 
    print x.return_code # which may be 1 or 2 
    # do what you want or 
    raise Exception(error) #optional 
else: 
    print "the output of %s is: %s" %(command, x) 
    print x.return_code # which is 0 
+2

Próbowałem powyższego wyniku z następującym wynikiem: 'TypeError: run() dostał nieoczekiwany argument słowa kluczowego 'capture'' z Fabric 1.10.2 i Paramiko 1.15.2. – DMfll

Powiązane problemy