问题描述
我正在开发一个通过 Runtime.getRuntime().exec(String[])
创建进程并在 Linux 中打开反向 ssh 隧道的应用程序。即使 Java 进程被终止,我也希望这条隧道能够持续存在。
我阅读了 Runtime.getRuntime().exec(String[])
的文档,它指定命令在单独的进程中执行:
在单独的进程中执行指定的命令和参数。
尽管如此,当运行 java 可执行文件的服务停止时:
systemctl stop myapp
Connection to localhost closed.
创建新进程的代码如下:
List<String> command = new ArrayList<>(Arrays.asList(
"/usr/bin/sshpass","-p",request.getHostPassword(),"ssh","-f","-N","-M","-S","/tmp/socket" + request.getHostUser() + request.getHostIp(),String.valueOf(request.getHostSshPort()),request.getHostUser() + "@" + request.getHostIp()
));
for (SSHPortMapping mapping: request.getPortMappings()) {
command.add("-R");
command.add(mapping.getPretty());
}
command.add("-o");
command.add("StrictHostKeyChecking=no");
Process process = Runtime.getRuntime().exec(command.toArray(new String[0]));
int result = process.waitFor();
...
如何在java中实现一个持久化进程,在服务停止时不会关闭所有反向ssh连接?
解决方法
根据命令及其语法,我将假设一个类 Unix 系统。
以 Runtime.getRuntime().exec
开头的命令确实在单独的进程中执行,但是当服务停止时,所有当前子进程都会被杀死。使用中间启动程序的简单方法。
如果它是一个选项,您可以使用一个小的 shell 脚本来获取相关参数,启动 ssh
命令,并立即存在而无需等待其子项。从那时起,没有直接父进程的 ssh
进程被 init 进程(PID 1)直接采用,不再是 java 应用程序进程组的成员。因此,当您停止运行 java 可执行文件的服务时,它们不应再被终止。