<i id='QsKMb'><tr id='QsKMb'><dt id='QsKMb'><q id='QsKMb'><span id='QsKMb'><b id='QsKMb'><form id='QsKMb'><ins id='QsKMb'></ins><ul id='QsKMb'></ul><sub id='QsKMb'></sub></form><legend id='QsKMb'></legend><bdo id='QsKMb'><pre id='QsKMb'><center id='QsKMb'></center></pre></bdo></b><th id='QsKMb'></th></span></q></dt></tr></i><div id='QsKMb'><tfoot id='QsKMb'></tfoot><dl id='QsKMb'><fieldset id='QsKMb'></fieldset></dl></div>

  • <legend id='QsKMb'><style id='QsKMb'><dir id='QsKMb'><q id='QsKMb'></q></dir></style></legend>
  • <small id='QsKMb'></small><noframes id='QsKMb'>

    1. <tfoot id='QsKMb'></tfoot>
        <bdo id='QsKMb'></bdo><ul id='QsKMb'></ul>

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

        时间:2023-07-22
      1. <small id='bDDnT'></small><noframes id='bDDnT'>

          • <bdo id='bDDnT'></bdo><ul id='bDDnT'></ul>
              <tbody id='bDDnT'></tbody>

                • <tfoot id='bDDnT'></tfoot>
                  <legend id='bDDnT'><style id='bDDnT'><dir id='bDDnT'><q id='bDDnT'></q></dir></style></legend>

                  <i id='bDDnT'><tr id='bDDnT'><dt id='bDDnT'><q id='bDDnT'><span id='bDDnT'><b id='bDDnT'><form id='bDDnT'><ins id='bDDnT'></ins><ul id='bDDnT'></ul><sub id='bDDnT'></sub></form><legend id='bDDnT'></legend><bdo id='bDDnT'><pre id='bDDnT'><center id='bDDnT'></center></pre></bdo></b><th id='bDDnT'></th></span></q></dt></tr></i><div id='bDDnT'><tfoot id='bDDnT'></tfoot><dl id='bDDnT'><fieldset id='bDDnT'></fieldset></dl></div>
                  本文介绍了以与长时间运行的 Python 进程不同的用户身份运行子进程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  我有一个长时间运行的守护程序 Python 进程,当某些事件发生时,它使用子进程生成新的子进程.长时间运行的进程由具有超级用户权限的用户启动.我需要它生成的子进程作为不同的用户(例如nobody")运行,同时保留父进程的超级用户权限.

                  I've got a long running, daemonized Python process that uses subprocess to spawn new child processes when certain events occur. The long running process is started by a user with super user privileges. I need the child processes it spawns to run as a different user (e.g., "nobody") while retaining the super user privileges for the parent process.

                  我正在使用

                  su -m nobody -c <program to execute as a child>
                  

                  但这似乎是重量级的,并没有死得很干净.

                  but this seems heavyweight and doesn't die very cleanly.

                  有没有办法以编程方式而不是使用 su 来完成此任务?我正在查看 os.set*uid 方法,但 Python std lib 中的文档在该区域非常稀疏.

                  Is there a way to accomplish this programmatically instead of using su? I'm looking at the os.set*uid methods, but the doc in the Python std lib is quite sparse in that area.

                  推荐答案

                  既然你提到了一个守护进程,我可以断定你是在一个类 Unix 操作系统上运行的.这很重要,因为如何做到这一点取决于操作系统的种类.此答案适用于 Unix,包括 Linux 和 Mac OS X.

                  Since you mentioned a daemon, I can conclude that you are running on a Unix-like operating system. This matters, because how to do this depends on the kind operating system. This answer applies only to Unix, including Linux, and Mac OS X.

                  1. 定义一个函数来设置正在运行的进程的gid和uid.
                  2. 将此函数作为 preexec_fn 参数传递给 subprocess.Popen

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

                  subprocess.Popen will use the fork/exec model to use your preexec_fn. That is equivalent to calling os.fork(), preexec_fn() (in the child process), and os.exec() (in the child process) in that order. Since os.setuid, os.setgid, and preexec_fn are all only supported on Unix, this solution is not portable to other kinds of operating systems.

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

                  The following code is a script (Python 2.4+) that demonstrates how to do this:

                  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()
                  

                  你可以像这样调用这个脚本:

                  You can invoke this script like this:

                  以 root 身份启动...

                  Start as 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...

                  Become non-root in a child process...

                  (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
                  

                  当子进程退出时,我们回到父进程的root ...

                  When the child process exits, we go back to root in parent ...

                  (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
                  

                  注意让父进程等待子进程退出只是为了演示目的.我这样做是为了让父母和孩子可以共享一个终端.守护进程没有终端,很少等待子进程退出.

                  Note that having the parent process wait around for the child process to exit is for demonstration purposes only. I did this so that the parent and child could share a terminal. A daemon would have no terminal and would seldom wait around for a child process to exit.

                  这篇关于以与长时间运行的 Python 进程不同的用户身份运行子进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  上一篇:子进程 readline 挂起等待 EOF 下一篇:Python分别从子进程stdout和stderr读取,同时保留顺序

                  相关文章

                  <tfoot id='PxJQB'></tfoot>

                • <legend id='PxJQB'><style id='PxJQB'><dir id='PxJQB'><q id='PxJQB'></q></dir></style></legend>

                    • <bdo id='PxJQB'></bdo><ul id='PxJQB'></ul>

                    <small id='PxJQB'></small><noframes id='PxJQB'>

                    1. <i id='PxJQB'><tr id='PxJQB'><dt id='PxJQB'><q id='PxJQB'><span id='PxJQB'><b id='PxJQB'><form id='PxJQB'><ins id='PxJQB'></ins><ul id='PxJQB'></ul><sub id='PxJQB'></sub></form><legend id='PxJQB'></legend><bdo id='PxJQB'><pre id='PxJQB'><center id='PxJQB'></center></pre></bdo></b><th id='PxJQB'></th></span></q></dt></tr></i><div id='PxJQB'><tfoot id='PxJQB'></tfoot><dl id='PxJQB'><fieldset id='PxJQB'></fieldset></dl></div>