【问题标题】:running python-daemon as non-priviliged user and keeping group-memberships以非特权用户身份运行 python-daemon 并保持组成员身份
【发布时间】:2013-06-28 13:18:42
【问题描述】:

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

现在我的问题是我想以非特权用户而不是(例如mydaemon)而不是root 身份运行守护进程。

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

root 启动的进程很好地守护进程并由正确的用户拥有,但我在尝试访问设备时收到 permission denied 错误。 我写了一个小测试应用,好像进程没有继承用户的group-memberships。

#!/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 完整组成员身份的守护进程?

【问题讨论】:

  • 这是什么 Linux 发行版?
  • ubuntu 和 debian(我相应地更新了问题)
  • 在启动 python 守护程序之前,您是否有无法更改为守护程序用户的原因?也许像(这个答案)[stackoverflow.com/a/8941040/651848] 可以满足您的需求?
  • @rkyser 是的,我现在正在这样做(请参阅我自己的答案),但它使文件权限的一些事情变得复杂(PID 文件通常创建在只有 root 可以写入的地方)跨度>

标签: python linux ubuntu python-daemon


【解决方案1】:

我当前的解决方案是在启动实际守护程序之前删除 root 权限,使用 start-stop-daemonchuid 参数:

 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 中编写该逻辑。

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

【讨论】:

    【解决方案2】:

    这个可以通过monkey patching daemon模块来解决,代码如下:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-07-08
      • 2017-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多