我想PR_SET_CHILD_SUBREAPER
为运行我的脚本的 Bash 进程设置进程标志,以便我可以获取在其生命周期内创建的子进程树(并且可以以无序方式杀死)。基本上,我希望 Bash 能够调用prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0);
自身,但我还没有找到实现这一目标的方法。有什么建议吗?
即使使用涉及使用 Bash 内置函数(如果存在)libc.so.6
prctl()
直接调用(a-la Python )的狡猾解决方案,我也可以接受。ctypes
答案1
既然你提到这对你来说没问题,我觉得有必要介绍 bash 的等价物......
ctypes.sh, bash 的外部函数接口
它是一个 bash 的共享对象插件,加载了 bash 的enable -f
机制:
enable [-a] [-dnps] [-f filename] [name ...]
该
-f
选项意味着在支持动态加载的系统上从共享对象文件名加载新的内置命令名。
并用C语言实现。它至少可以在大多数 Linux 发行版和 FreeBSD 上运行。
你必须编译并安装首先。主要功能是能够从 shell 使用几乎任何库调用或系统调用。尽管当内置函数struct
无法自动重建结构时,需要结构的调用可能会变得更加复杂。
在当前 bash shell 中、在 amd64 (x86_64) 架构和 Linux 内核 5.6 上键入的示例(在某些情况下,常量取决于架构和(更不常见)内核版本):
$ source /usr/local/bin/ctypes.sh
$ dlcall -r int prctl int:36 ulong:1 ulong:0 ulong:0 ulong:0
int:0
$ echo $DLRETVAL # you can't use $() above to get the result since that would be a subshell
int:0
$ echo $$; bash -c 'echo $$; sleep 99 & echo $!; disown -a'
14767
16761
16762
$ pstree -p $$
bash(14767)─┬─pstree(16778)
└─sleep(16762)
sleep
丢失其父进程(pid 16761)的进程已bash
被当前 shell 而不是 init 进程继承:它起作用了。
请注意,PR_SET_CHILD_SUBREAPER
必须替换为其在/usr/include/linux/prctl.h
此系统上找到的值(和类型):
#define PR_SET_CHILD_SUBREAPER 36
您必须检查文档才能正确使用它。
此外,shell 的标准wait
可能无法按预期工作:shell 不会生成该sleep
命令,因此该wait
命令不会执行任何操作。您可能需要投资 dlcallingwait()
、waitpid()
公司这可能很困难,因为 bash 本身会wait()
在每次运行命令时更改设置并使用 -like 调用,因此可能会发生一些不可预见的交互来处理这些继承的进程。
使用数据库
这将达到与以前相同的结果(必须有一些选项可以使其不那么冗长):
$ gdb -ex 'call (int)prctl((int)36,(long)1,(long)0,(long)0,(long)0)' -ex detach -ex quit -p $$
答案2
非 C 程序员可以使用一些简单的链加载工具。我为 nosh 工具集编写了一个这样的工具。
sh ./wibble
对于作为(或其他一些 shell)调用的脚本,只需运行本地收割者 true sh ./wibble
./wibble
对于简单运行调用的脚本本地收割者 true ./wibble
该工具在 FreeBSD 上的工作方式相同。它隐藏了所有系统调用差异。
进一步阅读
- 乔纳森·德博因·波拉德 (2018)。
local-reaper
。 nosh 工具集手册页。软件。 - https://unix.stackexchange.com/a/390089/5132