首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在命名空间中启动multiprocessing.process

在命名空间中启动multiprocessing.process
EN

Stack Overflow用户
提问于 2015-05-08 23:31:16
回答 3查看 1.5K关注 0票数 0

我正在尝试从一个已经创建的命名空间(名为'test')中启动一个新进程。

我研究了一些方法,包括nsenter:

代码语言:javascript
复制
import subprocess
from nsenter import Namespace

with Namespace(mypid, 'net'):
    # output network interfaces as seen from within the mypid's net NS:
    subprocess.check_output(['ip', 'a'])

但我似乎找不到在哪里找到var的参考资料,mypid…!

理想情况下,我希望将像nsenter这样的依赖项保持在最低限度(为了可移植性),所以我可能希望沿着ctype路线走下去,比如(尽管没有针对netns的syscall ...):

代码语言:javascript
复制
nsname = 'test'
netnspath = '%s%s' % ('/run/netns/', nsname)
netnspath = netnspath.encode('ascii')

libc = ctypes.CDLL('libc.so.6')

printdir(libc)

fd = open(netnspath)
print libc.syscall(???, fd.fileno())

或(摘自http://tech.zalando.com/posts/entering-kernel-namespaces-with-python.html)

代码语言:javascript
复制
import ctypes
libc = ctypes.CDLL('libc.so.6')
# replace MYPID with the container's PID
fd = open('/proc/<MYPID>/ns/net')
libc.setns(fd.fileno(), 0)
# we are now inside MYPID's network namespace

但是,我仍然需要知道PID,而且我的libc没有setns!

任何关于如何获得PID的想法都将是很棒的!

蒂娅!

EN

回答 3

Stack Overflow用户

发布于 2015-05-09 00:20:58

nsenter模块的问题在于,您需要为它提供一个已经在目标名称空间中运行的进程的PID。这意味着您不能实际使用这个模块来使用您使用ip netns add之类的东西创建的网络名称空间。

内核的setns()系统调用接受文件描述符,而不是PID。如果你愿意用ctypes解决这个问题,你可以这样做:

代码语言:javascript
复制
from ctypes import cdll
libc = cdll.LoadLibrary('libc.so.6')
_setns = libc.setns

CLONE_NEWIPC = 0x08000000
CLONE_NEWNET = 0x40000000
CLONE_NEWUTS = 0x04000000

def setns(fd, nstype):
    if hasattr(fd, 'fileno'):
        fd = fd.fileno()

    _setns(fd, nstype)

def get_netns_path(nspath=None, nsname=None, nspid=None):
    '''Generate a filesystem path from a namespace name or pid,
    and return a filesystem path to the appropriate file.  Returns
    the nspath argument if both nsname and nspid are None.'''

    if nsname:
        nspath = '/var/run/netns/%s' % nsname
    elif nspid:
        nspath = '/proc/%d/ns/net' % nspid

    return nspath

如果您的libc没有setns()调用,那么您可能就不走运了(尽管您在哪里运行的内核足够新,可以支持网络名称空间,但是libc却不支持?)。

假设您有一个名为"blue“的名称空间可用(ip netns add blue),您可以运行:

代码语言:javascript
复制
with open(get_netns_path(nsname="blue")) as fd:
    setns(fd, CLONE_NEWNET)
    subprocess.check_call(['ip', 'a'])

请注意,您必须以root身份运行此代码。

票数 2
EN

Stack Overflow用户

发布于 2015-05-09 01:07:43

这是可行的,但是我不确定0作为syscall的一部分会做什么。所以,如果有人能开导我,那就太好了!

代码语言:javascript
复制
import ctypes

nsname = 'test'
netnspath = '%s%s' % ('/run/netns/', nsname)
netnspath = netnspath.encode('ascii')

libc = ctypes.CDLL('libc.so.6')

fd = open(netnspath)
print libc.syscall(308, fd.fileno(), 0)
票数 0
EN

Stack Overflow用户

发布于 2016-01-08 23:12:37

在发现这个问题后,我们更新了python-nsenter,现在除了提供pid之外,它还可以通过任意路径进入名称空间。

例如,如果您想输入一个由ip netns add创建的名称空间,您现在可以这样做:

代码语言:javascript
复制
with Namespace('/var/run/netns/foo', 'net'):
    # do something in the namespace
    pass

带有此更新的Version 0.2 is now available via PyPi

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30127569

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档