以非特权用户身份运行python守护程序并保持组成员身份
我正在使用这个包用python编写一个守护进程。守护进程在启动时(init.d)启动,需要访问各种设备。 守护进程将在运行ubuntu的嵌入式系统()上运行 现在我的问题是,我想以非特权用户的身份运行守护程序,而不是以root用户的身份运行(例如以非特权用户身份运行python守护程序并保持组成员身份,python,linux,ubuntu,python-daemon,Python,Linux,Ubuntu,Python Daemon,我正在使用这个包用python编写一个守护进程。守护进程在启动时(init.d)启动,需要访问各种设备。 守护进程将在运行ubuntu的嵌入式系统()上运行 现在我的问题是,我想以非特权用户的身份运行守护程序,而不是以root用户的身份运行(例如mydaemon) 为了允许守护进程访问设备,我将该用户添加到所需的组中。 在python代码中,我使用daemon.DaemonContext(uid=uidofmydamon) 由root启动的进程可以很好地进行后台监控,并由正确的用户拥有,但在尝试
mydaemon
)
为了允许守护进程访问设备,我将该用户添加到所需的组中。
在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
)身份运行上述代码时,我得到:
如何创建由root启动但具有不同有效uid和完整组成员身份的守护进程?我当前的解决方案包括在启动实际守护进程之前,使用
启动停止守护进程的chuid
参数删除根权限:
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编写这种逻辑
现在这是可行的,但我认为这应该可以用一种更优雅的方式来解决。这可以通过对守护程序模块进行猴子补丁来解决,代码如下:
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
Linux发行版的目的是什么?ubuntu和debian(我相应地更新了这个问题)在启动python守护程序之前,有什么原因不能更改为守护程序用户吗?也许类似(这个答案)[可以满足您的需要吗?@rkyser是的,我现在正在这样做(请参见我自己的答案),但它会使文件权限的一些事情变得复杂(PID文件通常创建在只有root用户才能写的地方)
import daemon
daemon.daemon.change_process_owner = change_process_owner