你可以用一点 C 来做,只要你不担心几个条件,并且明白它会有局限性。
prctl(PR_SET_PDEATHSIG, …) 系统调用是 linux 内核的一部分,并且有一些规则 - 它不能在 fork() 中存在,它不能在 exec() 中存在到 setuid/setgid 二进制文件中。
限制是:
- 这是一个简单的程序,如果你从子进程中启动其他东西,它会杀死一切,除非你设置一些限制。
- 它不适用于相对罕见的可执行模型(例如 32->64 位)
- 它不适用于静态链接的二进制文件(很少见)
考虑到这些限制,我们可以从一些C 创建一个小的预加载库,它将调用这个系统调用。所以,例如:
#include <sys/prctl.h>
#include <sys/types.h>
#include <signal.h>
__attribute__((constructor))
static void on_load() {
prctl(PR_SET_PDEATHSIG, SIGTERM);
}
使用gcc -fPIC -shared -o term_death.so term_death.c编译
当您将LD_PRELOAD 环境变量与此二进制文件的完整路径一起使用时,任何启动的程序都会在其父进程被终止时发送SIGTERM。
这是 C 端的设置 - 我们现在有一个帮助程序库,它将允许您要求的行为。
让这个从 java 端工作。
我们需要将 .so 的完整路径注入到 ProcessBuilder 的 LD_PRELOAD 环境变量中,例如:
ProcessBuilder pb = new ProcessBuilder();
Map<String, String> env = pb.environment();
env.put("LD_PRELOAD", "/home/me/development/experiments/term_death.so");
同样,您需要指定.so 的路径,以便加载它。
当您pb.start() 时,它将继承LD_PRELOAD 环境变量。在加载可执行文件时,它会运行 on_load 代码(因为它被标记为构造函数)并表示当父进程终止时该进程将收到 SIGTERM。
这有点难看,但应该可以解决问题。