我正在使用python-daemon包在python中编写守护进程。守护进程在启动时(init.d)启动,需要访问各种设备。 守护程序将在运行ubuntu的嵌入式系统(beaglebone)上运行。
现在我的问题是我想以非特权用户身份运行守护程序(例如mydaemon
)而不是root
。
为了允许守护程序访问设备,我将该用户添加到所需的组。
在python代码中我使用daemon.DaemonContext(uid=uidofmydamon)
。
由root
daemonizes开始的进程很好并且由正确的用户拥有,但在尝试访问设备时我得到权限被拒绝错误。
我写了一个小测试应用程序,似乎该进程没有继承用户的组成员资格。
#!/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 和完整的组成员身份?
答案 0 :(得分:2)
我当前的解决方案是在启动实际守护程序之前使用chuid
的{{1}}参数删除root权限:
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中编写该逻辑。
现在有效,但我认为这应该以更优雅的方式解决。
答案 1 :(得分: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