5

我已将 Fabric 设置为使用 INFO 或更高级别记录所有与 SSH/Paramiko 相关的输出:

logging.basicConfig()
logging.getLogger('ssh.transport').setLevel(logging.INFO)

这导致日志如下所示:

[host1] Executing task 'task1'
[host1] Run: ls
...

是否可以更改 ssh.transport 记录器的格式化程序,以便每行旁边也打印日期和时间?

4

3 回答 3

6

正如alecxe 所说,该格式在 Fabric 1.x 中是硬编码的(截至我发布此版本时,这是唯一可用的版本。)有一个被拒绝的拉取请求可以解决这个问题。

因此,我们需要解决此问题。这是我编写的一个相当老套的解决方案,但它依赖于 Fabric 的未记录部分,这意味着它可能会在未来的版本中中断。

from fabric.io import OutputLooper
from datetime  import datetime

def newFlush(self, text):
    stamp = datetime.now().strftime("%a %b %d %H:%M:%S - ")
    print(stamp + text)

OutputLooper._flush = newFlush

从现在开始,远程机器的任何输出都将带有时间戳。

例如,如果没有此代码,则输出sudo('echo "test"')将是:

[InteractSL-DT1.usma.ibm.com] sudo: echo "test"
[InteractSL-DT1.usma.ibm.com] out: test
[InteractSL-DT1.usma.ibm.com] out:

'test'

但是在添加之后,你现在会得到这个:

[InteractSL-DT1.usma.ibm.com] sudo: echo "test"
Fri Jan 02 12:54:49 - [InteractSL-DT1.usma.ibm.com] out:
Fri Jan 02 12:54:49 - test

Fri Jan 02 12:54:49 - [InteractSL-DT1.usma.ibm.com] out:
Fri Jan 02 12:54:49 -

'test'

你可以玩弄这个基本的想法来清理它。输出开头的sudo行来自fabric.operations._run_command,在第 900 行附近。我不确定您可以修改它的任何简单方法。

于 2015-01-02T18:03:47.947 回答
4

现在不可能了。格式是硬编码的:参见source

仅供参考,有一个提案正在询问您的确切身份。


您可以使用内部设置日志记录格式asctime,但它不会影响结构输出,只会影响 paramiko 输出:

import logging
FORMAT = "%(asctime)s %(name)s %(message)s"
logging.basicConfig(format=FORMAT, level=logging.INFO)

示例输出:

[host] Executing task 'restart'
[host] sudo: ls
2013-09-23 02:36:54,800 paramiko.transport Connected (version 2.0, client OpenSSH_5.3)
2013-09-23 02:36:55,728 paramiko.transport Authentication (password) successful!
2013-09-23 02:36:55,889 paramiko.transport Secsh channel 1 opened.
...

希望有帮助。

于 2013-09-22T22:35:18.017 回答
0

除了更换_flush(). 我通常发现在任何类中替换私有方法都是一种冒险的做法,更不用说第三方了。这是一个装饰 Fabric_flush()方法并且还使用原生 Pythontime.asctime方法来格式化时间戳的解决方案。

def time_decorator(msg):
    """
    Decorates `msg` with current timestamp
    Args:
        msg(str): The log message from fabric
    Returns: 
        str: Original message prepended with current date time
    """
    if "\n" not in msg and msg.strip():
        return "[%s] %s" % (time.asctime(), msg)

    return msg


# Compose original method inside of decorator
_original_flush = OutputLooper._flush
OutputLooper._flush = lambda self, msg: {
    _original_flush(self, time_decorator(msg))
}


@task
def uptime():
    run('uptime')

测试一下,你的输出应该类似于:

> fab uptime -H 10.0.1.3,10.0.1.2
[10.0.1.3] Executing task 'uptime'
[10.0.1.3] run: uptime
[Thu Dec 15 19:34:35 2016] [10.0.1.3] out:  19:34:35 up 69 days,  4:22,  1 user,  load average: 0.05, 0.03, 0.05
[Thu Dec 15 19:34:35 2016] [10.0.1.3] out:

[10.0.1.2] Executing task 'uptime'
[10.0.1.2] run: uptime
[Thu Dec 15 19:34:35 2016] [10.0.1.2] out:  19:34:35 up 70 days,  1:12,  1 user,  load average: 0.00, 0.01, 0.05
[Thu Dec 15 19:34:35 2016] [10.0.1.2] out:


Done.
Disconnecting from ec2-user@10.0.1.3... done.
Disconnecting from ec2-user@10.0.1.2... done.
于 2016-12-15T19:44:42.300 回答