Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/316.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python子进程popen作为不同的用户执行_Python_Python 3.x_Subprocess - Fatal编程技术网

python子进程popen作为不同的用户执行

python子进程popen作为不同的用户执行,python,python-3.x,subprocess,Python,Python 3.x,Subprocess,我试图在Python3.6中以另一个用户的身份使用子流程中的popen执行一个命令,但它仍然会以调用脚本的用户的身份执行,我计划将其称为root。我使用的是线程,因此当两个线程并行执行时,不要侵犯用户权限是很重要的 proc = subprocess.Popen(['echo $USER; touch myFile.txt'], shell=True, env={'FOO':'bar', 'U

我试图在Python3.6中以另一个用户的身份使用子流程中的popen执行一个命令,但它仍然会以调用脚本的用户的身份执行,我计划将其称为root。我使用的是线程,因此当两个线程并行执行时,不要侵犯用户权限是很重要的

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

上面的示例仍然会创建用户id为1000的myFile.txt

我尝试了不同的方法:

如中所述,通过复制os.environment并更改用户等方式尝试使用。请注意,这是针对python 2的

按中所述尝试,使用start\u new\u session=True


我的最后一个选项是使用sudo-u username命令作为命令的前缀,但我认为这不是一种优雅的方式。

标准的方法[仅限POSIX]是使用preexec\u fn来设置gid和uid,如中更详细的描述

类似这样的操作应该可以做到这一点-为了完整性,我还修改了您的初始代码段,以包含您可能想要设置的其他环境变量,但仅设置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')

请注意,您还需要确保当前工作目录是可访问的,例如供降级用户写入,因为没有显式覆盖它。

标准方法[仅POSIX]是使用preexec_fn设置gid和uid,如中更详细的描述

类似这样的操作应该可以做到这一点-为了完整性,我还修改了您的初始代码段,以包含您可能想要设置的其他环境变量,但仅设置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')

请注意,您还需要确保当前工作目录是可访问的,例如供降级用户写入,因为没有明确覆盖它

这是否回答了您的问题?sudo-u用户名命令确实是一种优雅的方式@lemonhead我在第1条中提到过。@Chris有什么原因使这种方法不能达到你的目标吗?我认为您在示例中缺少的部分是通过将func传递到preexec来进行降级_fn@lemonhead正如我在第1节中提到的:我尝试了这种方法,但也不起作用。我调用了:subprocess.Popen['echo$USER;touch myFile.txt'],shell=True,env={'FOO':'bar','USER':'www-data'},stdout=subprocess.PIPE,preexec_fn=demoe33,demode返回异常demoe33,33这是否回答了您的问题?sudo-u用户名命令确实是一种优雅的方式@lemonhead我在第1条中提到过。@Chris有什么原因使这种方法不能达到你的目标吗?我认为您在示例中缺少的部分是通过将func传递到preexec来进行降级_fn@lemonhead正如我在第1节中提到的:我尝试了这种方法,但也不起作用。我调用了:subprocess.Popen['echo$USER;touch myFile.txt'],shell=True,env={'FOO':'bar','USER':'www-data'},stdout=subprocess.PIPE,preexec_fn=demoE33,33,demode返回了一个异常demoE33,33好的,这是可行的。。。甚至在线程中。我增加了一个单独的睡眠时间,效果很好。我不知道我以前做错了什么,但谢谢你。您使用的是preexec_fn参数,但在2下。在我的问题中,他们说在使用线程时必须使用start_new_session=True。您或其他人能给我解释一下吗?pylint打印一条警告:W1509:使用preexec_fn关键字,在线程存在的情况下可能不安全子进程popen pr eexec fn是在windows中使用未经piveleged的suer运行子进程的类似方法吗?i、 我的python脚本是以管理员的身份运行的,我想以非特权用户的身份运行子流程。好吧,这样可以。。。甚至在线程中。我增加了一个单独的睡眠时间,效果很好。我不知道我以前做错了什么,但谢谢你。您使用的是preexec_fn参数,但在2下。在我的问题中,他们说在使用线程时必须使用start_new_session=True。您或其他人能给我解释一下吗?pylint打印一条警告:W1509:使用preexec_fn关键字,在线程存在的情况下可能不安全子进程popen pr eexec fn是在windows中使用未经piveleged的suer运行子进程的类似方法吗?i、 我的python脚本正在以管理员的身份运行,我想以非特权用户的身份运行子流程