python子进程popen以其他用户身份执行

时间:2020-04-19 09:41:06

标签: python python-3.x subprocess

我正在尝试以python 3.6中与popen不同的用户身份在subprocess中执行命令,但该命令仍将以调用脚本的用户身份执行(我计划调用该脚本)作为根)。我正在使用线程,因此在2个线程并行执行时不要侵犯用户权限很重要。

proc = subprocess.Popen(['echo $USER; touch myFile.txt'],
                          shell=True,
                          env={'FOO':'bar', 'USER':'www-data'},
                          stdout=subprocess.PIPE)

上面的示例仍将使用我的myFile.txt创建user_id 1000

我尝试了不同的方法:

  1. 通过复制os.environment尝试Run child processes as different user from a long running Python process中所述,并更改了用户等。
    (请注意,这是针对python 2的)

  2. 使用start_new_session=True

    按照https://docs.python.org/3.6/library/subprocess.html#popen-constructor的说明进行尝试

我的最后一个选择是在命令前加上sudo -u username command,但我认为这不是一种优雅的方法。

1 个答案:

答案 0 :(得分:1)

[仅适用于POSIX]的标准方法是使用preexec_fn来设置gid和uid,如this answer

中所述

类似的事情应该可以解决问题-为了完整起见,我还修改了您的初始代码段以包含您可能想要设置的其他环境变量,但是简单地设置preexec_fn就足够了您正在运行的命令:

import os, pwd, subprocess

def demote(user_uid, user_gid):
    def result():
        os.setgid(user_gid)
        os.setuid(user_uid)
    return result

def exec_cmd(username):
    # get user info from username
    pw_record = pwd.getpwnam(username)
    homedir = pw_record.pw_dir
    user_uid = pw_record.pw_uid
    user_gid = pw_record.pw_gid
    env = os.environ.copy()
    env.update({'HOME': homedir, 'LOGNAME': username, 'PWD': os.getcwd(), 'FOO': 'bar', 'USER': username})

    # execute the command
    proc = subprocess.Popen(['echo $USER; touch myFile.txt'],
                              shell=True,
                              env=env,
                              preexec_fn=demote(user_uid, user_gid),
                              stdout=subprocess.PIPE)
    proc.wait()


exec_cmd('www-data')

请注意,您还需要确保降级的用户可以访问(例如,用于写入)当前工作目录,因为它不会明确覆盖它