linkkf 로직수정중

This commit is contained in:
2025-12-25 19:42:32 +09:00
parent 695d26767e
commit af9a38a973
128 changed files with 8711 additions and 1484 deletions

View File

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