j2ssh sshclient не ожидает завершения удаленной команды
У меня есть метод, который использует j2ssh sshclient для выполнения удаленной команды на сервере Linux. Выполнение удаленной команды может занять от нескольких секунд до более минуты. Мне нужна программа на Java, чтобы дождаться завершения выполнения команды, прежде чем продолжить, но это не так. Программа Java запускает команду, но затем продолжается до завершения удаленной команды. Вот мой метод:
//The connect is done prior to calling the method.
public static String executeCommand(String host, String command, String path)
throws Exception
{
cd(path);
System.out.println("-- ssh: executing command: " + command + " on "
+ host);
SessionChannelClient session = ssh.openSessionChannel();
session.startShell();
session.getOutputStream().write("sudo -s \n".getBytes());
session.getOutputStream().write(command.getBytes());
session.getOutputStream().write("\n exit\n".getBytes());
IOStreamConnector output = new IOStreamConnector();
java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
output.connect(session.getInputStream(), bos);
String theOutput = bos.toString();
System.out.println("output..." + theOutput);
session.close();
disconnect();
return theOutput;
}
2 ответа
Проблема здесь в том, что вы запускаете оболочку, выводите свои команды и затем выполняете операцию чтения, чтобы чтение из входного потока выполнялось в другом потоке. Основной поток вашей функции немедленно переходит к закрытию сеанса, поэтому ваша команда будет уничтожена до того, как будет получен весь вывод.
Чтобы предотвратить это, просто читайте из Inputstream сеанса, пока он не вернет EOF в том же потоке, то есть прекратите использование IOStreamConnector и прочитайте вручную в свой ByteArrayOutputStream. Затем вызовите session.close(), как только поток вернет EOF, поскольку это сигнализирует о том, что все данные были получены с сервера.
byte[] buf = new byte[1024];
int r;
ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
while((r = session.getInputStream().read(buf)) > -1) {
bos.write(buf, 0, r);
}
Это должно работать следующим образом:
//The connect is done prior to calling the method.
public static String executeCommand(String host, String command, String path)
throws Exception
{
cd(path);
System.out.println("-- ssh: executing command: " + command + " on "
+ host);
SessionChannelClient session = ssh.openSessionChannel();
if ( session.executeCommand(cmd) ) {
java.io.ByteArrayOutputStream bos = new java.io.ByteArrayOutputStream();
output.connect(session.getInputStream(), bos);
String theOutput = bos.toString();
System.out.println("output..." + theOutput);
}
session.close();