linkkf 로직수정중
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import io
|
||||
import json
|
||||
import locale
|
||||
import os
|
||||
import platform
|
||||
import queue
|
||||
@@ -20,7 +21,7 @@ def demote(user_uid, user_gid):
|
||||
class SupportSubprocess(object):
|
||||
|
||||
@classmethod
|
||||
def command_for_windows(cls, command: list) -> str or list:
|
||||
def command_for_windows(cls, command: list):
|
||||
if platform.system() == 'Windows':
|
||||
tmp = []
|
||||
if type(command) == type([]):
|
||||
@@ -43,17 +44,32 @@ class SupportSubprocess(object):
|
||||
|
||||
iter_arg = ''
|
||||
if platform.system() == 'Windows':
|
||||
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=shell, env=env, encoding='utf8')
|
||||
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=shell, env=env, encoding='utf8', bufsize=0)
|
||||
else:
|
||||
if uid == None:
|
||||
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=shell, env=env, encoding='utf8')
|
||||
else:
|
||||
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=shell, env=env, preexec_fn=demote(uid, gid), encoding='utf8')
|
||||
|
||||
|
||||
|
||||
new_ret = {'status':'finish', 'log':None}
|
||||
|
||||
def func(ret):
|
||||
with process.stdout:
|
||||
try:
|
||||
for line in iter(process.stdout.readline, iter_arg):
|
||||
ret.append(line.strip())
|
||||
if log:
|
||||
logger.debug(ret[-1])
|
||||
except:
|
||||
pass
|
||||
|
||||
result = []
|
||||
thread = threading.Thread(target=func, args=(result,))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
#thread.join()
|
||||
|
||||
try:
|
||||
#process.communicate()
|
||||
process_ret = process.wait(timeout=timeout) # wait for the subprocess to exit
|
||||
except:
|
||||
import psutil
|
||||
@@ -62,14 +78,17 @@ class SupportSubprocess(object):
|
||||
proc.kill()
|
||||
process.kill()
|
||||
new_ret['status'] = "timeout"
|
||||
|
||||
ret = []
|
||||
with process.stdout:
|
||||
for line in iter(process.stdout.readline, iter_arg):
|
||||
ret.append(line.strip())
|
||||
if log:
|
||||
logger.debug(ret[-1])
|
||||
|
||||
#logger.error(process_ret)
|
||||
thread.join()
|
||||
#ret = []
|
||||
#with process.stdout:
|
||||
# for line in iter(process.stdout.readline, iter_arg):
|
||||
# ret.append(line.strip())
|
||||
# if log:
|
||||
# logger.debug(ret[-1])
|
||||
|
||||
ret = result
|
||||
#logger.error(ret)
|
||||
if format is None:
|
||||
ret2 = '\n'.join(ret)
|
||||
elif format == 'json':
|
||||
@@ -82,20 +101,29 @@ class SupportSubprocess(object):
|
||||
break
|
||||
ret2 = json.loads(''.join(ret[index:]))
|
||||
except:
|
||||
ret2 = None
|
||||
ret2 = ret
|
||||
|
||||
new_ret['log'] = ret2
|
||||
return new_ret
|
||||
except Exception as exception:
|
||||
logger.error('Exception:%s', exception)
|
||||
except Exception as e:
|
||||
logger.error(f"Exception:{str(e)}")
|
||||
logger.error(traceback.format_exc())
|
||||
logger.error('command : %s', command)
|
||||
finally:
|
||||
try:
|
||||
if process.stdout:
|
||||
process.stdout.close()
|
||||
if process.stdin:
|
||||
process.stdin.close()
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
__instance_list = []
|
||||
|
||||
|
||||
def __init__(self, command, print_log=False, shell=False, env=None, timeout=None, uid=None, gid=None, stdout_callback=None, call_id=None):
|
||||
def __init__(self, command, print_log=False, shell=False, env=None, timeout=None, uid=None, gid=None, stdout_callback=None, call_id=None, callback_line=True):
|
||||
self.command = command
|
||||
self.print_log = print_log
|
||||
self.shell = shell
|
||||
@@ -108,6 +136,7 @@ class SupportSubprocess(object):
|
||||
self.stdout_queue = None
|
||||
self.call_id = call_id
|
||||
self.timestamp = time.time()
|
||||
self.callback_line = callback_line
|
||||
|
||||
|
||||
def start(self, join=True):
|
||||
@@ -127,13 +156,15 @@ class SupportSubprocess(object):
|
||||
self.command = self.command_for_windows(self.command)
|
||||
logger.debug(f"{self.command=}")
|
||||
if platform.system() == 'Windows':
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=self.shell, env=self.env, encoding='utf8', bufsize=0)
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=self.shell, env=self.env, encoding='utf8', bufsize=0)
|
||||
|
||||
else:
|
||||
if self.uid == None:
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=self.shell, env=self.env, encoding='utf8', bufsize=0)
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=self.shell, env=self.env, encoding='utf8', bufsize=0)
|
||||
else:
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, shell=self.shell, env=self.env, preexec_fn=demote(self.uid, self.gid), encoding='utf8', bufsize=0)
|
||||
self.process = subprocess.Popen(self.command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, shell=self.shell, env=self.env, preexec_fn=demote(self.uid, self.gid), encoding='utf8', bufsize=0)
|
||||
SupportSubprocess.__instance_list.append(self)
|
||||
self.send_stdout_callback(self.call_id, 'START', None)
|
||||
self.__start_communicate()
|
||||
self.__start_send_callback()
|
||||
if self.process is not None:
|
||||
@@ -142,17 +173,18 @@ class SupportSubprocess(object):
|
||||
self.process_close()
|
||||
else:
|
||||
self.process.wait()
|
||||
self.remove_instance(self)
|
||||
logger.info(f"{self.command} END")
|
||||
except Exception as e:
|
||||
logger.error(f'Exception:{str(e)}')
|
||||
logger.error(traceback.format_exc())
|
||||
logger.warning(self.command)
|
||||
if self.stdout_callback != None:
|
||||
self.stdout_callback('error', str(e))
|
||||
self.stdout_callback('error', str(traceback.format_exc()))
|
||||
self.send_stdout_callback(self.call_id, 'ERROR', str(e))
|
||||
self.send_stdout_callback(self.call_id, 'ERROR', str(traceback.format_exc()))
|
||||
finally:
|
||||
if self.stdout_callback != None:
|
||||
self.stdout_callback('thread_end', None)
|
||||
#self.stdout_callback(self.call_id, 'thread_end', None)
|
||||
pass
|
||||
|
||||
|
||||
def __start_communicate(self):
|
||||
@@ -164,7 +196,11 @@ class SupportSubprocess(object):
|
||||
|
||||
def rdr():
|
||||
while True:
|
||||
buf = self.process.stdout.read(1)
|
||||
try:
|
||||
buf = self.process.stdout.read(1)
|
||||
except:
|
||||
continue
|
||||
#print(buf)
|
||||
if buf:
|
||||
_queue.put( buf )
|
||||
else:
|
||||
@@ -192,7 +228,9 @@ class SupportSubprocess(object):
|
||||
if r is not None:
|
||||
#print(f"{r=}")
|
||||
self.stdout_queue.put(r)
|
||||
self.stdout_queue.put('\n')
|
||||
self.stdout_queue.put('<END>')
|
||||
self.stdout_queue.put('\n')
|
||||
for tgt in [rdr, clct]:
|
||||
th = threading.Thread(target=tgt)
|
||||
th.setDaemon(True)
|
||||
@@ -204,16 +242,36 @@ class SupportSubprocess(object):
|
||||
def func():
|
||||
while self.stdout_queue:
|
||||
line = self.stdout_queue.get()
|
||||
#logger.error(line)
|
||||
if line == '<END>':
|
||||
if self.stdout_callback != None:
|
||||
self.stdout_callback('end', None)
|
||||
self.send_stdout_callback(self.call_id, 'END', None)
|
||||
break
|
||||
else:
|
||||
if self.stdout_callback != None:
|
||||
self.stdout_callback('log', line)
|
||||
self.send_stdout_callback(self.call_id, 'LOG', line)
|
||||
self.remove_instance(self)
|
||||
|
||||
th = threading.Thread(target=func, args=())
|
||||
def func_callback_line():
|
||||
previous = ''
|
||||
while self.stdout_queue:
|
||||
receive = previous + self.stdout_queue.get()
|
||||
lines = receive.split('\n')
|
||||
previous = lines[-1]
|
||||
|
||||
for line in lines[:-1]:
|
||||
line = line.strip()
|
||||
# TODO
|
||||
#logger.error(line)
|
||||
if line == '<END>':
|
||||
self.send_stdout_callback(self.call_id, 'END', None)
|
||||
break
|
||||
else:
|
||||
self.send_stdout_callback(self.call_id, 'LOG', line)
|
||||
self.remove_instance(self)
|
||||
|
||||
if self.callback_line:
|
||||
th = threading.Thread(target=func_callback_line, args=())
|
||||
else:
|
||||
th = threading.Thread(target=func, args=())
|
||||
th.setDaemon(True)
|
||||
th.start()
|
||||
|
||||
@@ -243,6 +301,15 @@ class SupportSubprocess(object):
|
||||
self.process.stdin.write(f'{cmd}\n')
|
||||
self.process.stdin.flush()
|
||||
|
||||
def send_stdout_callback(self, call_id, mode, data):
|
||||
try:
|
||||
if self.stdout_callback != None:
|
||||
self.stdout_callback(self.call_id, mode, data)
|
||||
except Exception as e:
|
||||
logger.error(f'Exception:{str(e)}')
|
||||
logger.error(f"[{call_id}] [{mode}] [{data}]")
|
||||
#logger.error(traceback.format_exc())
|
||||
|
||||
|
||||
@classmethod
|
||||
def all_process_close(cls):
|
||||
@@ -271,4 +338,7 @@ class SupportSubprocess(object):
|
||||
for instance in cls.__instance_list:
|
||||
if instance.call_id == call_id:
|
||||
return instance
|
||||
|
||||
|
||||
@classmethod
|
||||
def get_list(cls):
|
||||
return cls.__instance_list
|
||||
|
||||
Reference in New Issue
Block a user