以非特权用户身份运行pythondaemon并保留组成员身份

2024-10-02 10:30:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用python编写一个守护进程,使用python-daemon包。守护进程在引导时(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的用户身份运行上述代码时,我得到的结果是

^{pr2}$

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

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

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


Tags: 代码用户uidstream进程oslogging身份
2条回答

这可以通过monkey修补守护程序模块来解决,代码如下:

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

然后是猴子补丁:

^{pr2}$

我当前的解决方案包括在启动实际守护程序之前删除根特权,使用chuid参数来表示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和{}),然后在启动实际的守护进程(具有适当的文件权限)。在

我宁愿用python而不是bash编写这种逻辑。在

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

相关问题 更多 >

    热门问题