2016-01-12 63 views
0

我已經創建了一個python腳本,它使用parallel-ssh模塊(AKA pssh)爲了在遠程節點上運行各種命令。其中一個命令是puppet agent -t,它使用ANSII顏色代碼輸出。 當腳本正在運行並輸出到終端時,着色按預期工作。然而,在腳本日誌我看到它不解析ANSII代碼,而是我得到一個醜陋的包裝的每一行,如下:格式記錄器忽略ANSII代碼 - Python日誌記錄

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... 

這是非常令人沮喪,因爲它使日誌的可讀性。 我試圖修改與re.compile(r'\x1b[^m]*m')方法記錄器的配置,我在this thread發現,像這樣:

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記錄器設置單獨的處理程序,但我無法找到它。

任何幫助將非常感謝!

+0

您當前的代碼取代了日誌模板,而不是實際的消息。解決這個問題最簡單的方法是清理記錄之前記錄的消息。 – Thtu

+0

你能否提供一些細節? pssh模塊有它自己的記錄器AFAIK,所以我不確定在記錄之前我能夠處理輸出。 謝謝! –

回答

2

您是否嘗試禁用傀儡顏色?

puppet agent -t --color=false 
+0

謝謝!這是解決這個問題的另一種方法,可以提供解決方案。但是,我確實喜歡stdout是用顏色打印的,所以如果有一種方法可以在終端中保持着色,並且在記錄輸出時忽略它,那就太好了。如果沒有找到這樣的選項,我想我會去你的建議:-) –

+0

你可以張貼你稱之爲「ParallelSSHClient」的代碼片段和你使用輸出的地方嗎? – MaxU

+0

client = pssh.ParallelSSHClient(nodes,pool_size = args.batch,timeout = 10,num_retries = 1) output = client.run_command(command,sudo = True) 輸出中的節點: for line in output [node] ['stdout']: print'[{0}] {1}'。format(node,line) 這就是整個模塊。 pssh模塊知道如何提取主機記錄器並使用它。 –

0

您當前的代碼只能轉義實際的日誌記錄模板。希望有人可以一起告訴你如何正確地做到這一點,但你可以使用一個日誌記錄適配器,它就像一個記錄器,除了它允許你修改記錄的消息。

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

+0

我粘貼了您提供的代碼,但在調用set_logger方法時發生錯誤: return MyAdapter(logger) TypeError:__init __()需要3參數(給出2) 我試着去理解哪些參數是__init__正在尋找,但是找不到它。 :-) 謝謝! –

0

這個版本保持原有產量,並增加了「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'] ] 
+0

嘿@MaxU 謝謝,我已經嘗試過,但不幸的是它只是將輸出更改爲標準輸出。即使進行此修改,日誌也保持不變。 –

+0

您可以從整個文本塊中刪除ANSI格式,並具有兩種版本:原始輸出和NOANSI輸出。我已經更新了答案中的代碼。 – MaxU