Java постоянный обратный SSH-процесс

#java #process

#java #процесс

Вопрос:

Я разрабатываю приложение, которое создает процесс через Runtime.getRuntime().exec(String[]) и открывает обратный ssh-туннель в Linux. Я хочу, чтобы этот туннель сохранялся, даже если 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(),
    "-p", 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-соединения при остановке службы?

Ответ №1:

Исходя из команд и их синтаксиса, я предположу, что это Unix-подобная система.

Команды, запущенные с Runtime.getRuntime().exec , действительно выполняются в отдельных процессах, но обычно все текущие дочерние элементы уничтожаются при остановке службы. Простой способ использовать промежуточный процесс запуска.

Если это вариант, вы могли бы использовать крошечный сценарий оболочки, который получал бы соответствующие параметры, запускал ssh команды и немедленно существовал, не дожидаясь своих дочерних элементов. С этого момента ssh процессы, не имеющие прямого родителя, напрямую принимаются процессом инициализации (PID 1) и больше не являются членами группы процессов приложения Java. Из-за этого они больше не должны уничтожаться при остановке службы, которая запускает исполняемый файл java.

Комментарии:

1. Здравствуйте, спасибо за ваш быстрый ответ. Я создал скрипт, /root/reverse.sh который создаст подоболочку внутри процесса и выполнит обратную команду ssh : (sshpass -p password ssh .....) . Затем в коде Java я просто вызываю Runtime.getRuntime.exec("/bin/bash /root/reverse.sh") . Затем я получаю PID процесса с ps -aux помощью и получаю PID 1640. Наконец, я получаю дерево PID с: pstree -sg 1640 , которое выводит: systemd(1)───ssh(1640) . Таким образом, это проверяет, что процесс SSH принадлежит systemd(1) . Несмотря на все это, когда я останавливаю службу, процесс завершается. Есть идеи?

2. @PauMAVA: Я годами так не программировал, поэтому я не уверен. Я думаю, что в последних версиях Linux есть понятие группы процессов, которое не просто связано с PPID, как то, что я использовал в 80-х годах… Если у вас здесь нет ответов, вы можете попробовать задать вопрос в Unix amp; Linux или ServerFault

3. Хорошо, буду запрашивать там ответ, поскольку это проблема с PID, которая, я думаю, подходит лучше. Я поддержу ваш ответ, поскольку он привел меня в правильном направлении. Спасибо!