我正在尝试从一个已经创建的命名空间(名为'test')中启动一个新进程。
我研究了一些方法,包括nsenter:
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 ...):
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)
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的想法都将是很棒的!
蒂娅!
发布于 2015-05-09 00:20:58
nsenter模块的问题在于,您需要为它提供一个已经在目标名称空间中运行的进程的PID。这意味着您不能实际使用这个模块来使用您使用ip netns add之类的东西创建的网络名称空间。
内核的setns()系统调用接受文件描述符,而不是PID。如果你愿意用ctypes解决这个问题,你可以这样做:
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),您可以运行:
with open(get_netns_path(nsname="blue")) as fd:
setns(fd, CLONE_NEWNET)
subprocess.check_call(['ip', 'a'])请注意,您必须以root身份运行此代码。
发布于 2015-05-09 01:07:43
这是可行的,但是我不确定0作为syscall的一部分会做什么。所以,如果有人能开导我,那就太好了!
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)发布于 2016-01-08 23:12:37
在发现这个问题后,我们更新了python-nsenter,现在除了提供pid之外,它还可以通过任意路径进入名称空间。
例如,如果您想输入一个由ip netns add创建的名称空间,您现在可以这样做:
with Namespace('/var/run/netns/foo', 'net'):
# do something in the namespace
passhttps://stackoverflow.com/questions/30127569
复制相似问题