Java持久化反向SSH进程

问题描述

我正在开发一个通过 Runtime.getRuntime().exec(String[]) 创建进程并在 Linux 中打开反向 ssh 隧道的应用程序。即使 Java 进程被终止,我也希望这条隧道能够持续存在。

我阅读了 Runtime.getRuntime().exec(String[]) 的文档,它指定命令在单独的进程中执行:

在单独的进程中执行指定的命令和参数。

尽管如此,当运行 java 可执行文件的服务停止时:

systemctl stop myapp

所有活动的反向 SSH 隧道都会自动关闭

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 可执行文件的服务时,它们不应再被终止。