我正在尝试在 python 3.6
中以不同的用户身份使用 subprocess
中的 popen
执行命令,但它仍将以用户身份执行谁调用了脚本(我打算以 root 身份调用它)。我正在使用线程,因此当 2 个线程并行执行时不侵犯用户权限很重要。
proc = subprocess.Popen(['echo $USER; touch myFile.txt'],
shell=True,
env={'FOO':'bar', 'USER':'www-data'},
stdout=subprocess.PIPE)
上面的例子仍然会用我的 user_id 1000
创建 myFile.txt
我尝试了不同的方法:
按照 Run child processes as different user from a long running Python process 中的描述进行了尝试通过复制 os.environment 并更改用户等
(注意这是针对 python 2 的)按照 https://docs.python.org/3.6/library/subprocess.html#popen-constructor 中的描述进行了尝试通过使用
start_new_session=True
我最后的选择是在命令前加上 sudo -u username command
但我认为这不是优雅的方式。
最佳答案
[仅适用于 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')
请注意,您还需要确保降级用户可以访问当前工作目录(例如,用于写入),因为不会显式覆盖它
关于python子进程popen以不同用户身份执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61302291/