0

I have method that uses j2ssh sshclient to execute a remote command on a linux server. The remote command can take anywhere from a few seconds to over a minute to execute. I need the Java program to wait until the command is finished executing before proceeding, but it doesn't. The Java program runs the command but then continues before the remote command finishes. Here's my method:

//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;

  }
caris
  • 31
  • 1
  • 5

2 Answers2

1

The problem here is that your starting the shell, outputting your commands and then threading off the read operation so reading from the Inputstream is performed on another thread. The main thread of your function moves immediately onto closing the session so your command will get killed before all the output is received.

In order to prevent this simply read from the session's Inputstream until it returns EOF on the same thread i.e. remove the use of the IOStreamConnector and read manually into your ByteArrayOutputStream. Then call session.close() once the stream returns EOF as this signals all data has been received from the server.

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);
}
0

It should work the following way:

//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();
Tomáš Cigánek
  • 121
  • 1
  • 15