我知道 Linux 命名空间,除其他外,可用于安全地处理限制和监禁子进程,而不会导致它们被僵尸化并转储到init
.但我对实施细节很模糊。我如何使用和提供的工具util-linux
来观察、监视并确保启动的所有进程都是另一个进程的直接命名空间后代?mount
nsenter
答案1
创建PID命名空间
此处使用的正确命令是unshare
.请注意,执行此操作所需的选项只能从util-linux 2.23
.这个想法是创建一个新的PID命名空间对于您正在运行的程序,其所有子程序也都在此名称空间中创建。您只需执行以下操作即可在新的 PID 命名空间中运行命令:
sudo unshare -fp some_command
要运行 shell,只需省略该命令即可。这将创建一个进程,该进程及其任何子进程将像往常一样在父(系统)命名空间内拥有 PID。然而,在新的命名空间中,它将具有 PID1
以及进程的一些特殊特征init
。从监控的角度来看,也许最相关的特征是,如果它的任何后代成为孤儿,它们将被重新设置为该进程而不是真正的init
进程的父进程。
对于大多数监控案例来说,简单地这样做可能就足够了。如前所述,命名空间内的进程在父命名空间内都有 PID,因此可以使用常规命令来监视它们的活动。我们还可以保证,如果命名空间中的任何进程成为孤立进程,它都不会从顶级程序 PID 下的进程树分支中掉出来,这意味着它仍然可以轻松跟踪。
与挂载命名空间结合
然而,我们不能做的是监控进程的 PID想那就是有。为此,特别是为了能够ps
在新命名空间中使用该命令,您需要为该procfs
命名空间安装一个单独的文件系统。这又导致了另一个问题,因为唯一ps
接受 for 的位置procfs
是/proc
.一种解决方案是创建一个chroot
监狱并在那里安装新的procfs
。但这是一种麻烦的方法,因为至少我们需要将我们打算使用的任何二进制文件以及它们依赖的任何库复制(或至少硬链接)到新根。
解决方案也是使用新的挂载命名空间。在此我们可以procfs
使用真正的根目录的方式挂载新的/proc
,可以在 PID 命名空间中使用并且不会干扰其他任何东西。为了使这个过程非常简单,该unshare
命令提供了以下--mount-proc
选项:
sudo unshare -fp --mount-proc some_command
现在,ps
在组合命名空间中运行将仅显示具有 PID 命名空间的进程,并将显示 PID 为 的顶级进程1
。
关于什么nsenter
?
顾名思义,nsenter
可用于输入已使用 . 创建的命名空间unshare
。如果我们只想从其他不相关的脚本获取仅从命名空间内部可用的信息,这非常有用。最简单的方法是访问命名空间内运行的任何程序的 PID。需要明确的是,这必须是正在运行的命名空间内的目标程序的 PID nsenter
(由于命名空间可以嵌套,因此单个进程可能有多个 PID)。要在目标 PID/mount 命名空间中运行 shell,只需执行以下操作:
sudo nsenter -t $PID -m -p
如果按上述方式设置此命名空间,ps
则现在将仅列出该命名空间内的进程。