77 lines
2.8 KiB
Python
77 lines
2.8 KiB
Python
import json
|
|
import os
|
|
import platform
|
|
import subprocess
|
|
import traceback
|
|
|
|
from . import logger
|
|
|
|
|
|
class SupportSubprocess(object):
|
|
|
|
# 2021-10-25
|
|
# timeout 적용
|
|
@classmethod
|
|
def execute_command_return(cls, command, format=None, force_log=False, shell=False, env=None, timeout=None, uid=0, gid=0):
|
|
def demote(user_uid, user_gid):
|
|
def result():
|
|
os.setgid(user_gid)
|
|
os.setuid(user_uid)
|
|
return result
|
|
try:
|
|
if platform.system() == 'Windows':
|
|
tmp = []
|
|
if type(command) == type([]):
|
|
for x in command:
|
|
if x.find(' ') == -1:
|
|
tmp.append(x)
|
|
else:
|
|
tmp.append(f'"{x}"')
|
|
command = ' '.join(tmp)
|
|
|
|
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')
|
|
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}
|
|
try:
|
|
process_ret = process.wait(timeout=timeout) # wait for the subprocess to exit
|
|
except:
|
|
import psutil
|
|
process = psutil.Process(process.pid)
|
|
for proc in process.children(recursive=True):
|
|
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 force_log:
|
|
logger.debug(ret[-1])
|
|
|
|
if format is None:
|
|
ret2 = '\n'.join(ret)
|
|
elif format == 'json':
|
|
try:
|
|
index = 0
|
|
for idx, tmp in enumerate(ret):
|
|
#logger.debug(tmp)
|
|
if tmp.startswith('{') or tmp.startswith('['):
|
|
index = idx
|
|
break
|
|
ret2 = json.loads(''.join(ret[index:]))
|
|
except:
|
|
ret2 = None
|
|
|
|
new_ret['log'] = ret2
|
|
return new_ret
|
|
except Exception as exception:
|
|
logger.error('Exception:%s', exception)
|
|
logger.error(traceback.format_exc())
|
|
logger.error('command : %s', command)
|