Fabric日志格式显示日期和时间

时间:2013-09-22 22:12:50

标签: python fabric paramiko

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

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

这导致日志看起来像这样:

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

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

3 个答案:

答案 0 :(得分:5)

作为alecxe said,格式在Fabric 1.x中进行了硬编码(截至我发布时,这是唯一可用的版本。)有a rejected pull request可以解决此问题。

所以我们需要一个解决方法。这是我写的一个相当hacky的解决方案,但它依赖于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行附近。我不确定您是否可以修改它。

答案 1 :(得分:3)

现在不可能。格式为硬编码:请参阅source

仅供参考,有一个proposal正在询问你到底是什么。


您可以在内部使用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.
...

希望有所帮助。

答案 2 :(得分:0)

除了替换_flush()之外,我也无法找到办法。我通常发现在任何类中替换私有方法都是一种冒险的做法,更不用说第三方了。这是一个装饰Fabric _flush()方法的解决方案,也使用本机Python time.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.