Fabric: 如何在部分故障期间读取 ThreadingGroup 中的结果?

创建于 2018-05-14  ·  5评论  ·  资料来源: fabric/fabric

最好在文档中包含这样的示例。 假设我有这个代码。

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. 

假设 web1 和 web3 成功,而 web2 连接失败或命令返回非零退出代码。

  • 引发异常后如何获取这些详细信息?
  • 是否保证只有在所有操作完成后才会引发异常?

任何帮助表示赞赏。

最有用的评论

你好,

除了 shadyabhi 的评论,这里是我用来处理 GroupException 的一种方式。
我希望这个能帮上忙 !!

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



(如果来自ActivCloud支持)

所有5条评论

@shadyabhi

不确定您是在尝试捕获特定异常,还是只想捕获在单独线程中发生的所有异常。 我认为 ThreadingGroup 对象已经使用队列传递异常对象,如果在执行过程中遇到任何异常对象,则会引发。 我能够使用以下代码片段查看堆栈跟踪:

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

在命令行上我运行: fab thread-exception-example

@bossjones

感谢回复。 但是,我没有使用 fab 命令,而是通过使用 fabric 作为库来执行所有这些。 因此,答案仍然悬而未决,将不胜感激。

换句话说, fab正在处理我自己想要在我的代码中处理的内容。 我不想直接使用fab命令是有原因的,因为我希望在调用任务时有更大的灵活性。

谢谢

大家好,

对不起,我忽略了细节。 检查了面料代码并获得了详细信息。

GroupException 的参数是一个字典,键为fabric.connection.Connection对象,值为fabric.runners.Result对象。

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

你好,

除了 shadyabhi 的评论,这里是我用来处理 GroupException 的一种方式。
我希望这个能帮上忙 !!

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



(如果来自ActivCloud支持)

感谢@akiuni你的例子! 我是 Python/Fabric 的新手,这有助于我了解如何使用 ThreadedGroup 发出请求,并在出现异常时收集结果。 这是您示例的扩展版本。 非常感激! 对于它的价值,我也将其发布到 Stackoverflow

# 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()

此页面是否有帮助?
0 / 5 - 0 等级