M. Mitchley
M. Mitchley

Reputation: 41

Java and SSH causing hangs

I'm attempting to execute four commands on a remote server in Java. Since the commands involve exports, I've chained them together into one command:

rm -f nohup.out && export <a few similar commands> && nohup #here I execute a 
startup script#>nohup.out >nohup.out 2>nohup.err </dev/null &

I then want to wait a bit (around 30 seconds) and parse an IP address from nohup.out. The problem I'm having is that the program hangs and doesn't seem to break the connection - debug code indicates it breaks somewhere in the code block below, since it does in fact execute the command server-side successfully

How do I successfully shut the connection?

The sending code, which uses JSch and comes from an upvoted solution on this site is as follows. There is a debug line after this that is never reached.

((ChannelExec)channel).setCommand(command);
    InputStream commandOutput = channel.getInputStream();
    channel.connect();
    int readByte = commandOutput.read();

    while(readByte != 0xffffffff)
    //while (true)
    {
       outputBuffer.append((char)readByte);
       readByte = commandOutput.read();
    }

Upvotes: 0

Views: 1001

Answers (1)

iocanel
iocanel

Reputation: 580

I've had similar issues, with other kind of streams I was reading (e.g. websockets). Most of the time, it's about read() blocking and not reacting well to interruption. If this is the case, you may need to force close the channel or swith to non-blocking (maybe using available() or something like that).

Even better instead of doing polling reads, you can just specify the outputstream you want.

Here's a working example:

     executor = (ChannelExec) session.openChannel("exec");
        executor.setPty(true);
        executor.setCommand(script);
        executor.setOutputStream(output);
        executor.setErrStream(error);
        executor.connect();
        int errorStatus = -1;

        for (int i = 0; !executor.isClosed(); i++) {
            if (i > 0) {
                long delayMs = (long) (200L * Math.pow(i, 2));
                Thread.sleep(delayMs);
            }
            if ((errorStatus = executor.getExitStatus()) != -1) {
                break;
            }
        }
        LOGGER.debug("Output: {}", output.toString());
        LOGGER.debug("Error:  {}", error.toString());

Upvotes: 1

Related Questions