2017-10-22 17 views
0

개요 : 두 개의 스크립트, 로깅 용 (ddlog), 다른 하나는 ssh 연결 및 명령 실행 (ddlogin) 용으로 paramiko를 사용합니다. 로거는 잘 작동하고 내가 연결하는 각 호스트에 대한 로그 파일을 생성하지만 표준 입력 및 표준 출력 처리기는 로깅 이벤트를 트리거하지 않습니다. 현재 아래의 io 오류가 발생합니다. 나는 sys.stdout으로 logging.StreamHandler()를 수정하려고 시도했으나이 중 하나가 작동하지 않는 것 같습니다.(sys.) stdout을 로깅으로 리디렉션 (python3)

오류 :

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() 
+0

왜 출력 전용 파일에서 읽으려고합니까? –

+0

안녕하세요 Ignacio, 그래서 내가 원격 호스트 (dmesg, whoami, 등 ..) 명령을 실행하고 출력 로그 파일에 저장됩니다. –

+0

그 대신에'stdout'을 의미하지 않았습니까? –

답변

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() 

나는 믿을 수 없어 :

A)를 더 많은 사람들이 간단하고 쉽게 재사용 할 로깅 모듈을하지 않습니다. dev에 의해 제안 된 로깅 솔루션을 보았습니다. 코드는 8 개의 다른 장소에 있습니다. 모듈, 메소드, INIT 등 페이지 전체에 구토처럼 보입니다!

B) 스택 오버플로에 도움이되는 유일한 사람은 OP와 동일한 문제가 있거나 문제가있는 사람입니다. 나머지는 단지 명성을 인위적으로 팽창 시키려하지만 위의 사람과 같은 코멘트 섹션에 쓸모없는 쓰레기를 게시하려고합니다.