为什么基于取消共享的查杀只能与 --fork 一起可靠地工作?

nh2*_*nh2 7 process kill namespace unshare

这个答案中我们了解到,您可以通过 Linux PID 命名空间实现对整个进程子树的可靠终止unshare -p

这是我不明白的问题:

  • 仅当我使用-f/--fork选项取消共享时它才有效。

    unshare -fp -- bash -c "watch /bin/sleep 10000 && echo hi"
    
    Run Code Online (Sandbox Code Playgroud)

    当我运行这个时,kill -9那个的PID bash,然后观看,睡眠等都死了,正如我所希望的那样。

  • 但是当我使用它时没有-f

    unshare -p -- bash -c "watch /bin/sleep 10000 && echo hi"
    
    Run Code Online (Sandbox Code Playgroud)

    kill -9bash PID,然后将其watch重新设置为PID 1(在我的Ubuntu上是systemd),所以我没有达到杀死所有孩子的预期效果。

问题:

  • 为什么--fork必须要达到预期的效果?为什么不unshare使用exec()fork 还不够?
  • 有解决方法吗?我更希望能够方便地发送到通过开始杀死其下面的所有内容kill -9而创建的 PID 。unshare但是当我使用 时--fork,杀死我开始时返回的 pidunshare将简单地杀死unsharebash重新设置为 PID 1,因为unshare它不在我的 PID 命名空间中。

请注意,&& echo hi是必需的,因为如果您只向 发出一个命令bash -c,它就会执行exec()此操作,因此 bash 进程会消失(被替换),并且您无法杀死其 PID。

nh2*_*nh2 7

正如这个有用的答案中所描述的-nunshare(CLONE_NEWPID)仅对分叉的第一个子进程起作用。

特别是,man 2 unshareCLONE_NEWPID

取消共享 PID 命名空间,以便调用进程为其子进程拥有一个新的 PID 命名空间,该命名空间不与任何先前存在的进程共享。

调用进程不会移动到新的命名空间中。

调用进程创建的第一个子进程init(1)将具有进程 ID 1,并将承担新命名空间中的角色。


修补unshare以使查杀工作可靠

自从提出我的问题以来,在过去的几个小时里,我编写了一个补丁util-linux此处拉取请求),--kill-childunshare.

编辑:现在已作为 util-linux 的一部分合并并发布v2.32

你可以这样使用它:

unshare -fp --kill-child -- bash -c "watch /bin/sleep 10000 && echo hi"
Run Code Online (Sandbox Code Playgroud)

并且终止unshare将按预期撕毁整个进程树。

没有root

如果您的内核通过传递标志root启用了用户命名空间 ( ) ,您甚至可以在没有特权的情况下使用它:CONFIG_USER_NS=y-U

unshare -Ufp --kill-child -- bash -c "watch /bin/sleep 10000 && echo hi"
Run Code Online (Sandbox Code Playgroud)