您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

以与长期运行的Python进程不同的用户身份运行子进程

以与长期运行的Python进程不同的用户身份运行子进程

既然您提到了守护程序,我可以得出结论,您正在运行于类Unix操作系统上。这很重要,因为如何执行此操作取决于操作系统类型。这个答案适用 于 ,包括Linux和Mac OS X.

subprocess.Popen将使用fork / exec模型来使用您的preexec_fn。这等效于按此顺序调用os.fork(),preexec_fn()(在子进程中)和os.exec()(在子进程中)。由于os.setuid,os.setgid和preexec_fn仅在Unix上受支持,因此该解决方案不能移植到其他类型的操作系统上。

以下代码一个脚本(Python 2.4+),演示了如何执行此操作:

import os
import pwd
import subprocess
import sys


def main(my_args=None):
    if my_args is None: my_args = sys.argv[1:]
    user_name, cwd = my_args[:2]
    args = my_args[2:]
    pw_record = pwd.getpwnam(user_name)
    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 = os.environ.copy()
    env[ 'HOME'     ]  = user_home_dir
    env[ 'LOGNAME'  ]  = user_name
    env[ 'PWD'      ]  = cwd
    env[ 'USER'     ]  = user_name
    report_ids('starting ' + str(args))
    process = subprocess.Popen(
        args, preexec_fn=demote(user_uid, user_gid), cwd=cwd, env=env
    )
    result = process.wait()
    report_ids('finished ' + str(args))
    print 'result', result


def demote(user_uid, user_gid):
    def result():
        report_ids('starting demotion')
        os.setgid(user_gid)
        os.setuid(user_uid)
        report_ids('finished demotion')
    return result


def report_ids(msg):
    print 'uid, gid = %d, %d; %s' % (os.getuid(), os.getgid(), msg)


if __name__ == '__main__':
    main()

您可以像这样调用此脚本:

以root身份启动…

(hale)/tmp/demo$ sudo bash --norc
(root)/tmp/demo$ ls -l
total 8
drwxr-xr-x  2 hale  wheel    68 May 17 16:26 inner
-rw-r--r--  1 hale  staff  1836 May 17 15:25 test-child.py

成为非root用户的子进程…

(root)/tmp/demo$ python test-child.py hale inner /bin/bash --norc
uid, gid = 0, 0; starting ['/bin/bash', '--norc']
uid, gid = 0, 0; starting demotion
uid, gid = 501, 20; finished demotion
(hale)/tmp/demo/inner$ pwd
/tmp/demo/inner
(hale)/tmp/demo/inner$ whoami
hale

当子进程退出时,我们返回到父进程的根目录…

(hale)/tmp/demo/inner$ exit
exit
uid, gid = 0, 0; finished ['/bin/bash', '--norc']
result 0
(root)/tmp/demo$ pwd
/tmp/demo
(root)/tmp/demo$ whoami
root

,让父进程等待子进程退出只是出于 演示目的 。我这样做是为了使父母和孩子可以共享一个终端。守护程序将没有终端,并且很少等待子进程退出

python 2022/1/1 18:37:54 有442人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶