fdi.utils.run_proc 源代码

# -*- coding: utf-8 -*-

from .common import lls, trbk
import pwd
from os import chown, chmod, environ, setuid, setgid
from subprocess import Popen, PIPE, TimeoutExpired, run as srun

import logging
# create logger
logger = logging.getLogger(__name__)


[文档]def run_proc(cmd, as_user, pwdir, timeout): """ Execute a shell command and return status. """ try: # https://stackoverflow.com/a/6037494 pw_record = pwd.getpwnam(as_user) user_name = pw_record.pw_name user_home_dir = pw_record.pw_dir user_uid = pw_record.pw_uid user_gid = pw_record.pw_gid env = environ.copy() env['HOME'] = user_home_dir env['LOGNAME'] = user_name env['PWD'] = pwdir env['USER'] = user_name def chusr(user_uid, user_gid): def result(): setgid(user_gid) setuid(user_uid) logger.debug('set uid=%d gid=%d' % (user_uid, user_gid)) return result executable = None # /etc/sudoer: apache ALL:(vvpp) NOPASSWD: ALL # gpasswd -a vvpp apache # cmd = ['sudo', '-u', as_user, 'bash', '-l', '-c'] + cmd # cmd = ['sudo', '-u', as_user] + cmd logger.debug('Popen %s env:%s uid: %d gid:%d' % (str(cmd), lls(env, 40), user_uid, user_gid)) proc = Popen(cmd, executable=executable, stdin=PIPE, stdout=PIPE, stderr=PIPE, preexec_fn=None, cwd=pwdir, env=env, shell=False, encoding='utf-8') # , universal_newlines=True) except Exception as e: msg = trbk(e) return {'returncode': -1, 'message': msg} sta = {'command': str(cmd)} try: sta['stdout'], sta['stderr'] = proc.communicate(timeout=timeout) sta['returncode'] = proc.returncode except TimeoutExpired: # The child process is not killed if the timeout expista, # so in order to cleanup properly a well-behaved application # should kill the child process and finish communication # https://docs.python.org/3.6/library/subprocess.html?highlight=subprocess#subprocess.Popen.communicate proc.kill() sta['stdout'], sta['stderr'] = proc.communicate() sta['returncode'] = proc.returncode return sta