将(sys。)stdout重定向到日志记录(python3)

时间:2017-10-22 09:48:15

标签: python python-3.x logging stdout sys

概述:两个脚本,一个用于记录(ddlog),另一个脚本使用paramiko进行ssh连接和命令执行(ddlogin)。记录器运行良好并为我连接的每个主机创建日志文件,但标准输入和标准输出的处理程序不会触发记录事件。目前我得到以下io错误。我试图用sys.stdout修改logging.StreamHandler(),但这似乎也不起作用。

错误:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "ddlogin.py", line 89, in run
    main(host)
  File "ddlogin.py", line 60, in main
    line = sys.stdout.read().splitlines(4096)
io.UnsupportedOperation: not readable

ddlog:

import logging

fileLogger = logging.getLogger()
fileLogger.setLevel(logging.DEBUG)

switch_log_levels = {
    'debug':    fileLogger.debug,
    'info':     fileLogger.info,
    'warning':  fileLogger.warning,
    'error':    fileLogger.error,
    'critical': fileLogger.critical
}


def setup( logFile):
    global fileLogger

    logFormatStr = "[%(asctime)s %(threadName)s, %(levelname)s] %(message)s"
    consoleFormatStr = "[%(threadName)s, %(levelname)s] %(message)s"


    # File Handler for log file
    logFormatter = logging.Formatter(logFormatStr)
    fileHandler = logging.FileHandler(logFile )
    fileHandler.setFormatter( logFormatter )
    fileLogger.addHandler( fileHandler )

    # Stream Handler for stdout, stderr
    consoleFormatter = logging.Formatter(consoleFormatStr)
    consoleHandler = logging.StreamHandler()
    consoleHandler.setFormatter( consoleFormatter )
    consoleHandler.setLevel(logging.INFO)
    fileLogger.addHandler( consoleHandler )

def event( string, level='debug',print_screen=False, remove_newlines=False ):

    if remove_newlines:
        string = string.replace('\r', '').replace('\n', ' ')

    if print_screen:
        switch_log_levels[level](string)

    switch_log_levels[level](string)

ddlogin:

import argparse, ddlog, os, paramiko, sys
from threading import Thread
from queue import Queue

def main(hostlist):
    global username, password, commands

    try:
        # Filepath, logger, and console handler
        logfile = os.getcwd() + '//logs/' + hostlist + '.log'
        ddlog.setup(logfile)

        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            ssh.connect(hostlist, username=username, password=password)
        except paramiko.AuthenticationException:
            ddlog.event("[-] Failed to Authenticate.",'error')
            pass
        except paramiko.SSHException:
            ddlog.event("[-] An SSH exception was raised. Check clients ssh settings.",'error') #, exc_info=True)
            pass
        except TimeoutError:
            ddlog.event("[-] host is not reachable.",'error')
            pass

        host = hostlist.strip('\n')
        ddlog.event('[+] successfully connected to ' + host,'info')

        for command in commands:
            stdin, stdout, stderr = ssh.exec_command(command)
            stdin.close()
            line = sys.stdout.read().splitlines(4096)
            ddlog.event('[+] ' + host + line.strip().decode('ascii'),'info')

    except KeyboardInterrupt:
        sys.exit('[-] Process aborted by user input')

if __name__ == "__main__":
        # system arguments: ddlogin.py -u admin -p password -l 192.168.1.1 -c dmesg 'uname -a'
        parser = argparse.ArgumentParser()
        parser.add_argument('-u', '--username', action='store', dest='username', help='The ssh username.')
        parser.add_argument('-p', '--password', action='store', dest='password', help='The ssh password.')
        parser.add_argument('-l', '--hostlist', nargs='+',action='store', dest='hostlist', help='List of devices to interact with.')
        parser.add_argument('-c', '--commands', nargs='+',action='store', dest='commands', help='An exact list of commands to run.')
        #parser.add_argument('-o', '--output', nargs='+',action='store', dest='commands', help='TBD...')
        args = parser.parse_args()
        username = args.username
        password = args.password
        hostlist = args.hostlist
        commands = args.commands


        class ParallelConnections(Thread):
            def __init__(self, queue):
                Thread.__init__(self)
                self.queue = queue

            def run(self):
                while True:
                    host = self.queue.get()
                    main(host)
                    self.queue.task_done()

        thread_count = 4
        queue = Queue()

        for i in range(thread_count):
            Parallel = ParallelConnections(queue)
            Parallel.daemon = True
            Parallel.start()

        for host in hostlist:
            queue.put(host)

        queue.join()

1 个答案:

答案 0 :(得分:0)

感谢this wonderful post我找到了答案,并构建了以下解决方案。希望其他人面临记录问题将阅读这篇文章。

  for command in commands:
        stdin, stdout, stderr = ssh.exec_command(command, get_pty=True)
        lines = iter(stdout.readline, "")
        for line in lines:
            ddlog.event('[+] '+line,'info')
        stdin.close()