【问题标题】:Format logger to ignore ANSII code - Python logging格式化记录器以忽略 ANSII 代码 - Python 日志记录
【发布时间】:2016-01-15 02:29:23
【问题描述】:

我创建了一个使用parallel-ssh 模块(AKA pssh)的python 脚本,以便在远程节点上运行各种命令。其中一个命令是puppet agent -t,它使用ANSII 颜色代码输出。 当脚本运行并输出到终端时,着色按预期工作。但是,在脚本日志中,我看到它没有解析 ANSII 代码,而是为每一行得到了一个丑陋的包装器,如下所示:

2016-01-12 20:23:30,748  INFO: [ubuntu01]       ESC[1;31mWarning: Setting templatedir is deprecated. See http://links.puppetlabs.com/env-settings-deprecations
2016-01-12 20:23:30,748  INFO: [ubuntu01]       (at /usr/lib/ruby/vendor_ruby/puppet/settings.rb:1139:in `issue_deprecation_warning')ESC[0m
2016-01-12 20:23:30,749  INFO: [ubuntu01]       ESC[0;32mInfo: Retrieving pluginESC[0m
2016-01-12 20:23:31,984  INFO: [ubuntu01]       ESC[0;32mInfo: Caching catalog for ubuntu01.puppetlabESC[0m
2016-01-12 20:23:32,014  INFO: [ubuntu01]       ESC[0;32mInfo: Applying configuration version '1452623010'ESC[0m
2016-01-12 20:23:32,083  INFO: [ubuntu01]       ESC[mNotice: Finished catalog run in 0.08 secondsESC[0m
2016-01-12 20:23:32,351  INFO: [ubuntu01]       * agent is running
2016-01-12 20:23:32,353  INFO: [centos01]       ESC[0;32mInfo: Retrieving pluginfactsESC[0m
2016-01-12 20:23:32,353  INFO: [centos01]       ESC[0;32mInfo: Retrieving pluginESC[0m
2016-01-12 20:23:33,712  INFO: [centos01]       ESC[0;32mInfo: Caching catalog for centos01.puppetlabESC[0m
2016-01-12 20:23:33,838  INFO: [centos01]       ESC[0;32mInfo: Applying configuration version '1452623010'ESC[0m
2016-01-12 20:23:34,101  INFO: [centos01]       ESC[mNotice: Finished catalog run in 0.27 secondsESC[0m
2016-01-12 20:23:34,421  INFO: [centos01]       puppet (pid  2069) is running...

这很令人沮丧,因为它降低了日志的可读性。 我尝试使用在this thread 中找到的re.compile(r'\x1b[^m]*m') 方法修改记录器配置,如下所示:

import logging
import re

ansi_escape = re.compile(r'\x1b[^m]*m')
message = ansi_escape.sub('', '%(message)s')


def set_logger(log_file):
    """Define the logger.."""
    try:
        logging.basicConfig(filename=log_file, level=logging.INFO,
                        format='%(asctime)s  %(levelname)s: ' + message)
        logger = logging.getLogger(__name__)
        return logger
    except IOError:
        print "ERROR: No permissions to access the log file! Please run the script as root user (sudo will also do the trick)..\n"
        exit(2)

脚本运行正常,但没有任何更改,而且所有这些 ANSII 代码的日志看起来仍然很混乱。 我认为可能还有其他地方可以为 pssh 记录器设置单独的处理程序,但我找不到它。

任何帮助将不胜感激!

【问题讨论】:

  • 您当前的代码替换了日志模板,而不是实际的消息。解决此问题的最简单方法是在记录的消息被记录之前清理它们。
  • 你能提供更多细节吗? pssh 模块有它自己的记录器 AFAIK,所以我不确定我是否能够在输出被记录之前对其进行操作。谢谢!

标签: python logging ssh


【解决方案1】:

您是否尝试禁用人偶颜色?

puppet agent -t --color=false

【讨论】:

  • 谢谢!这是解决此问题的另一种方法,可以提供解决方案。但是,我确实喜欢标准输出以颜色打印的事实,所以如果有一种方法可以将颜色保留在终端中并在记录输出时忽略它,那就太好了。如果找不到这样的选项,我想我会接受你的建议:-)
  • 你能在你调用“ParallelSSHClient”的地方和你使用输出的地方发布代码吗?
  • client = pssh.ParallelSSHClient(nodes, pool_size=args.batch, timeout=10, num_retries=1) output = client.run_command(command, sudo=True) for node in output: for line in output[node]['stdout']: print '[{0}] {1}'.format(node, line) 这就是整个块。 pssh 模块知道如何拉取主机记录器并使用它。
  • 仅供参考-我已将 --color=false 添加到我的 puppet 命令中,它确实可以完成工作!所以现在我将使用它,除非这里有人能够解决日志记录问题。非常感谢!无论哪种方式,我都会将您的帖子标记为可能的答案:-)
【解决方案2】:

您当前的代码只会转义实际的日志记录模板。希望有人能过来告诉您如何正确执行此操作,但您可以使用日志适配器,它类似于记录器,只是它允许您修改正在记录的消息。

class myAdapter(logging.LoggerAdapter):

    def process(self, msg, kwargs):
        msg = re.sub(r'\x1b[^m]*m', '', msg)
        return '%s' % (msg), kwargs

def set_logger(log_file):
    """Define the logger.."""
    try:
        logging.basicConfig(filename=log_file, level=logging.INFO,
                    format='%(asctime)s  %(levelname)s: ' + message)
        logger = logging.getLogger(__name__)
        return myAdapter(logger, {})
    except IOError:
        print "ERROR: No permissions to access the log file! Please run the script as root user (sudo will also do the trick)..\n"
        exit(2)

更多信息可以在日志记录手册中找到:https://docs.python.org/2/howto/logging-cookbook.html

【讨论】:

  • 我已经粘贴了您提供的代码,但是在调用 set_logger 方法时出现错误:return MyAdapter(logger) TypeError: init__() 恰好需要 3 个参数(给定 2 个)我'我试图了解 __init 到底在寻找哪些参数,但找不到它。想了解更多信息吗? :-) 谢谢!
【解决方案3】:

此版本保留原始输出并添加“stdout.noansi”,因此您将拥有原始输出和没有 ANSI 格式的输出

import re

client = pssh.ParallelSSHClient(nodes, pool_size=args.batch, timeout=10, num_retries=1)

output = client.run_command(command, sudo=True)

for node in output:
    # let's remove ansi formatting and put it into 'stdout.noansi'...
    output[node]['stdout.noansi'] = re.sub(r'\x1b\[[^m]*?m', '', output[node]['stdout'], re.I | re.S | re.M)
    print '--------------- <<<<< NOANSI OUTPUT >>>>> ---------------'
    [print '[{0}] {1}'.format(node, line) for line in output[node]['stdout.noansi'] ]
    print '--------------- <<<<< ORIGINAL OUTPUT >>>>> ---------------'
    [print '[{0}] {1}'.format(node, line) for line in output[node]['stdout'] ]

【讨论】:

  • 嘿@MaxU 谢谢,我已经尝试过了,但不幸的是它只会将输出更改为标准输出。即使进行了此修改,日志也保持不变。
  • 您可以从整个文本块中删除 ANSI 格式并具有两个版本:原始输出和 NOANSI 输出。我已经更新了答案中的代码。
猜你喜欢
  • 2013-12-15
  • 2019-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多