2017-10-22 2 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와 동일한 문제가 있거나 문제가있는 사람입니다. 나머지는 단지 명성을 인위적으로 팽창 시키려하지만 위의 사람과 같은 코멘트 섹션에 쓸모없는 쓰레기를 게시하려고합니다.

관련 문제