Fabric: Wie liest man Ergebnisse in ThreadingGroup bei teilweisen Fehlern?

Erstellt am 14. Mai 2018  ·  5Kommentare  ·  Quelle: fabric/fabric

Es wird gut sein, auch ein Beispiel dafür in die Dokumentation aufzunehmen. Nehmen wir an, ich habe diesen Code.

from fabric import ThreadingGroup as Group
from fabric.exceptions import GroupException

hosts = ['web1', 'web2', 'web3']
g = Group(*hosts)

try:
    results = g.run('date', hide='both')
except GroupException as e:
    print e.args # I read from code that arguments are passed to exception but I'm unable to use that. `args` argument in my case is an empty tuple. 

Nehmen wir an, dass web1 und web3 erfolgreich waren, während web2 keine Verbindung herstellen konnte oder der Befehl mit einem Exit-Code ungleich Null zurückgegeben wurde.

  • Wie erhalte ich diese Details, nachdem die Ausnahme ausgelöst wurde?
  • Ist garantiert, dass die Ausnahme erst ausgelöst wird, nachdem alle Operationen abgeschlossen sind?

Jede Hilfe ist willkommen.

Hilfreichster Kommentar

Hallo,

Zusätzlich zu Shadyabhis Kommentar ist hier eine Methode, mit der ich mit GroupException umgehe.
Ich hoffe das hilft!!

import logging, socket, paramiko.ssh_exception
from fabric import Connection, Config, ThreadingGroup, exceptions, runners

...

g = ThreadingGroup.from_connections(c)
try:
    result = g.run('hostname' )  # (just a basic command)
except exceptions.GroupException as e:
    i = 0
    for c, r in e.result.items():
        print("Host[{}] = [{}]".format(i,c.host) )
        if isinstance(r,runners.Result) :
            print("ok, fine")
        elif isinstance(r,socket.gaierror) :
            print("Network error")
        elif isinstance(r,paramiko.ssh_exception.AuthenticationException) :
            print("Auth failed")
        else:
            print("something else")
        i+=1



(erhalten, wenn vom ActivCloud- Support)

Alle 5 Kommentare

Hey @shadyabhi ,

Sie sind sich nicht sicher, ob Sie versuchen, eine bestimmte Ausnahme abzufangen, oder ob Sie nur alle Ausnahmen abfangen möchten, die in separaten Threads auftreten. Ich denke, das ThreadingGroup-Objekt übergibt bereits Ausnahmeobjekte mithilfe von Warteschlangen und Erhöhungen, falls während der Ausführung irgendwelche auftreten. Ich konnte Stack-Traces mit dem folgenden Code-Snippet sehen:

def run_data(c):
    c.run('date', hide='both')

<strong i="8">@task</strong>
def thread_exception_example(c):
    hosts = ['localhost', 'fakehost', 'localhost']

    # python list comprehension
    {c: run_data(c) for c in Group(*hosts)}

Auf der Befehlszeile habe ich Folgendes ausgeführt: fab thread-exception-example

Hallo @bossjones ,

Danke für die Antwort. Ich verwende jedoch nicht den Befehl fab, sondern führe dies alles aus, indem ich Fabric als Bibliothek verwende. Eine Antwort steht also noch aus und wäre dankbar.

Mit anderen Worten, fab handhabt, was ich in meinem Code selbst handhaben möchte. Es gibt Gründe, warum ich den Befehl fab nicht direkt verwenden möchte, da ich mehr Flexibilität beim Aufrufen von Aufgaben haben möchte.

Danke

Hallo allerseits,

Tut mir leid, ich habe die Details übersehen. Den Stoffcode überprüft und Details erhalten.

Das Argument mit GroupException ist ein Wörterbuch mit dem Schlüssel als fabric.connection.Connection -Objekt und dem Wert als fabric.runners.Result -Objekt.

except GroupException as e:
         for c, r in e.result.items():
             print "Connection: {}, Result: {}".format(c, r)

Hallo,

Zusätzlich zu Shadyabhis Kommentar ist hier eine Methode, mit der ich mit GroupException umgehe.
Ich hoffe das hilft!!

import logging, socket, paramiko.ssh_exception
from fabric import Connection, Config, ThreadingGroup, exceptions, runners

...

g = ThreadingGroup.from_connections(c)
try:
    result = g.run('hostname' )  # (just a basic command)
except exceptions.GroupException as e:
    i = 0
    for c, r in e.result.items():
        print("Host[{}] = [{}]".format(i,c.host) )
        if isinstance(r,runners.Result) :
            print("ok, fine")
        elif isinstance(r,socket.gaierror) :
            print("Network error")
        elif isinstance(r,paramiko.ssh_exception.AuthenticationException) :
            print("Auth failed")
        else:
            print("something else")
        i+=1



(erhalten, wenn vom ActivCloud- Support)

Danke @akiuni für dein Beispiel! Ich bin neu bei Python/Fabric und das hat mir geholfen zu verstehen, wie man Anfragen mit ThreadedGroup macht und die Ergebnisse sammelt, wenn es eine Ausnahme gab. Hier ist meine erweiterte Version Ihres Beispiels. Sehr geschätzt! Für das, was es wert ist, habe ich dies auch auf Stackoverflow gepostet .

# requires fabric 2.x - run 'pip install fabric' to install it
import logging, socket, paramiko.ssh_exception
from fabric import Connection, Config, SerialGroup, ThreadingGroup, exceptions, runners
from fabric.exceptions import GroupException


# Note: You need to supply your own valid servers here to ssh to of course!
def main():
    testHosts("All should succeed", "validServer1,validServer2,validServer3")
    testHosts("Some should fail", "validServer1,validServer2,BADSERVER1,validServer3,BADSERVER2")

def testHosts(message, hostsAsString):
    print("")
    print(message)

    # Get list of hosts from somewhere, and convert them to connections
    hosts = hostsAsString.split(",")
    servers = [Connection(host=host) for host in hosts]

    # Create a thread group to run requests in parallel
    g = ThreadingGroup.from_connections(servers)
    try:
        command = "df -h / | tail -n1 | awk '{print $5}'"
        results = g.run(command, hide=True)
        for r in results:
            connection = results[r]
            print("{}".format(r.host) )
            print("  SUCCESS, " + connection.stdout.strip())
    except GroupException as e:
        # If an exception occurred, at least one request failed. 
        # Iterate through results here
        for c, r in e.result.items():
            print("{}".format(c.host) )
            if isinstance(r,runners.Result) :
                print("  SUCCESS, " + r.stdout.strip())
            elif isinstance(r,socket.gaierror) :
                print("  FAILED,  Network error")
            elif isinstance(r,paramiko.ssh_exception.AuthenticationException) :
                print("  FAILED,  Auth failed")
            else:
                print("  FAILED,  Something other reason")

main()

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

SamuelMarks picture SamuelMarks  ·  3Kommentare

Grazfather picture Grazfather  ·  4Kommentare

bitprophet picture bitprophet  ·  4Kommentare

jmcgrath207 picture jmcgrath207  ·  5Kommentare

bitprophet picture bitprophet  ·  6Kommentare