6

我正在使用python-daemon包在 python 中编写一个守护进程。守护程序在引导时启动 (init.d),需要访问各种设备。守护进程将在运行 ubuntu的嵌入式系统 ( beaglebone ) 上运行。

现在我的问题是我想以非特权用户而不是(例如mydaemon)而不是root.

为了允许守护进程访问设备,我将该用户添加到所需的组中。在我使用的 python 代码中daemon.DaemonContext(uid=uidofmydamon)

由守护进程启动的root进程很好,并且由正确的用户拥有,但是在尝试访问设备时出现权限被拒绝错误。我写了一个小测试应用程序,似乎该进程没有继承用户的组成员身份。

#!/usr/bin/python
import logging, daemon, os

if __name__ == '__main__':
  lh=logging.StreamHandler()
  logger = logging.getLogger()
  logger.setLevel(logging.INFO)
  logger.addHandler(lh)

  uid=1001 ## UID of the daemon user
  with daemon.DaemonContext(uid=uid,
                            files_preserve=[lh.stream],
                            stderr=lh.stream):
    logger.warn("UID : %s" % str(os.getuid()))
    logger.warn("groups: %s" % str(os.getgroups()))

当我以 uid=1001 的用户身份运行上述代码时,我得到类似

$ ./testdaemon.py
UID: 1001
groups: [29,107,1001]

而当我以root(或)身份运行上述代码时su,我得到:

$ sudo ./testdaemon.py
UID: 1001
groups: [0]

如何创建由 root 启动但具有不同的有效 uid完整组成员身份的守护进程?

4

2 回答 2

2

我当前的解决方案涉及在启动实际守护程序之前删除 root 权限,使用chuid参数 for start-stop-daemon

 start-stop-daemon \
      --start \
      --chuid daemonuser \
      --name testdaemon \
      --pidfile /var/run/testdaemon/test.pid \
      --startas /tmp/testdaemon.py \
     -- \
      --pidfile /var/run/testdaemon/test.pid \
      --logfile=/var/log/testdaemon/testdaemon.log

这个解决方案的缺点是,在启动实际的守护程序(具有适当的文件权限)之前,我需要创建守护程序应该写入的所有目录(特别是/var/run/testdaemon/var/log/testdaemon) 。

我宁愿在 python 中而不是 bash 中编写该逻辑。

现在可行,但我认为这应该以更优雅的方式解决。

于 2013-07-02T15:09:09.473 回答
0

这可以通过猴子补丁守护程序模块来修复,代码如下:

import os, grp, pwd

class DaemonError(Exception):
    pass

class DaemonOSEnvironmentError(DaemonError, OSError):
    pass

def change_process_owner(uid, gid):
    try:
        # This line adds all the groups the user is member of
        # to keep the expected permissions
        os.setgroups(
            [g.gr_gid for g in grp.getgrall()
                if pwd.getpwuid(uid).pw_name in g.gr_mem
            ]
        )
        os.setgid(gid)
        os.setuid(uid)
    except Exception, exc:
        error = DaemonOSEnvironmentError(u"Unable to change process 
                    owner (%(exc)s)" % vars())
        raise error

然后是猴子补丁:

import daemon
daemon.daemon.change_process_owner = change_process_owner
于 2018-07-06T16:57:56.310 回答