从这个答案我们了解到,您可以通过 Linux PID 命名空间实现对整个进程子树的可靠终止unshare -p
。
这是我不明白的问题:
-f
仅当我使用/--fork
选项取消共享时它才有效。unshare -fp -- bash -c "watch /bin/sleep 10000 && echo hi"
当我运行这个时,
kill -9
那个的PIDbash
,然后观看,睡眠等都死了,正如我所希望的那样。但是当我使用它时没有
-f
:unshare -p -- bash -c "watch /bin/sleep 10000 && echo hi"
和
kill -9
bash PID,然后watch
将其重新设置为PID 1(在我的Ubuntu上是systemd),所以我没有达到杀死所有孩子的预期效果。
问题:
- 为什么
--fork
必须要达到预期的效果?为什么不unshare
使用exec()
fork 还不够? - 有解决方法吗?我更希望能够方便地发送到通过开始杀死其下面的所有内容而
kill -9
创建的 PID 。unshare
但是当我使用 时--fork
,杀死我开始时返回的 pidunshare
将简单地杀死unshare
并bash
重新设置为 PID 1,因为unshare
它不在我的 PID 命名空间中。
请注意,&& echo hi
是必需的,因为如果您只向 发出一个命令bash -c
,它就会exec()
执行此操作,因此 bash 进程会消失(被替换),并且您无法杀死其 PID。
答案1
如上所述在这个有用的答案中-n
( )的效果unshare(CLONE_NEWPID)
仅对分叉的第一个子进程起作用。
尤其,男人2取消分享说的是CLONE_NEWPID
:
取消共享 PID 命名空间,以便调用进程为其子进程拥有一个新的 PID 命名空间,该命名空间不与任何先前存在的进程共享。
调用进程不会移动到新的命名空间中。
调用进程创建的第一个子进程
init(1)
将具有进程 ID 1 并将在新命名空间中承担 的角色。
修补unshare
以使查杀工作可靠
自从问我的问题以来,在过去的几个小时里我写了一个补丁util-linux
(在这里拉取请求) 向 中添加一个--kill-child
标志unshare
。
编辑:现在它已作为 util-linux 的一部分合并并发布v2.32
。
你可以这样使用它:
unshare -fp --kill-child -- bash -c "watch /bin/sleep 10000 && echo hi"
并且unshare
终止将按预期撕毁整个进程树。
没有root
root
如果您的内核CONFIG_USER_NS=y
通过传递标志启用了用户命名空间 ( ),您甚至可以在没有特权的情况下使用它-U
:
unshare -Ufp --kill-child -- bash -c "watch /bin/sleep 10000 && echo hi"