使用multiprocessing.Manager()时多用户出现权限被拒绝
我有一个以管理员身份运行的程序,它需要创建一些线程,让这些线程以不同的用户身份运行。这部分现在运行得很好,但我需要一种方法来让子进程和父进程之间进行沟通。
当我尝试使用multiprocessing.Manager()来处理一些列表、字典、锁、队列等时,总是会出现权限被拒绝的错误,尤其是在那些权限降低的进程中。
有没有办法给某个用户或进程ID(PID)授予访问权限,以解决这个问题呢?
以下是我遇到问题的基本代码(以管理员身份运行):
#!/usr/bin/env python
import multiprocessing, os
manager = multiprocessing.Manager()
problematic_list = manager.list()
os.setuid(43121) # or whatever your user is
problematic_list.append('anything')
结果:
root@liberator:/home/bscable# python asd.py
Traceback (most recent call last):
File "asd.py", line 8, in <module>
problematic_list.append('anything')
File "<string>", line 2, in append
File "/usr/lib/python2.7/multiprocessing/managers.py", line 755, in _callmethod
self._connect()
File "/usr/lib/python2.7/multiprocessing/managers.py", line 742, in _connect
conn = self._Client(self._token.address, authkey=self._authkey)
File "/usr/lib/python2.7/multiprocessing/connection.py", line 169, in Client
c = SocketClient(address)
File "/usr/lib/python2.7/multiprocessing/connection.py", line 293, in SocketClient
s.connect(address)
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
socket.error: [Errno 13] Permission denied
Traceback (most recent call last):
File "/usr/lib/python2.7/multiprocessing/util.py", line 261, in _run_finalizers
finalizer()
File "/usr/lib/python2.7/multiprocessing/util.py", line 200, in __call__
res = self._callback(*self._args, **self._kwargs)
File "/usr/lib/python2.7/multiprocessing/managers.py", line 625, in _finalize_manager
process.terminate()
File "/usr/lib/python2.7/multiprocessing/process.py", line 137, in terminate
self._popen.terminate()
File "/usr/lib/python2.7/multiprocessing/forking.py", line 165, in terminate
os.kill(self.pid, signal.SIGTERM)
OSError: [Errno 1] Operation not permitted
第一个异常似乎是这里最重要的。
1 个回答
1
Python(至少是2.6版本)使用一种叫做UNIX套接字的方式来进行通信,样子大概是这样的:
/tmp/pymp-eGnU6a/listener-BTHJ0E
我们可以获取这个路径,然后像这样修改它的权限:
#!/usr/bin/env python
import multiprocessing, os, grp, pwd
manager = multiprocessing.Manager()
problematic_list = manager.list()
fullname = manager._address
dirname = os.path.dirname(fullname)
gid = grp.getgrnam('some_group').gr_gid
uid = pwd.getpwnam('root').pw_uid # should always be 0, but you never know
os.chown(dirname, uid, gid)
os.chmod(dirname, 0770)
os.chown(fullname, uid, gid)
os.chmod(fullname, 0770)
os.setgid(gid)
os.setuid(43121) # or whatever your user is
problematic_list.append('anything')