python子进程popen作为不同的用户执行
我试图在Python3.6中以另一个用户的身份使用子流程中的popen执行一个命令,但它仍然会以调用脚本的用户的身份执行,我计划将其称为root。我使用的是线程,因此当两个线程并行执行时,不要侵犯用户权限是很重要的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
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脚本正在以管理员的身份运行,我想以非特权用户的身份运行子流程