0

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();
    }
M. Mitchley
  • 41
  • 1
  • 3
  • What do you need the `nohup` and `&` for? – Martin Prikryl Sep 15 '17 at 12:19
  • The server-side script I run spits out a lot of stuff, which I don't care about - I only care about one line that contains an IP address. Frankly, I don't know much about ssh, so potentially I don't need the nohup at all. My thinking on it was that it'd suppress the output, and allow for the java program to shut down without killing the server-side program. Am I wrong in using it? – M. Mitchley Sep 15 '17 at 12:32
  • The other option I can think of without nohup would be to continuously monitor the server output until the IP address shows up – M. Mitchley Sep 15 '17 at 14:11
  • Edit: it turns out the orphaned processes are due to a fault on the server-side script being executed, so not relevant to this problem – M. Mitchley Sep 15 '17 at 14:27
  • See also [How to read JSch command output?](https://stackoverflow.com/q/6902386/850848) – Which shows how to *correctly* read both standard and error output simultaneously, to allow command to complete and to collect all output including the errors. – Martin Prikryl Nov 11 '20 at 16:23

1 Answers1

1

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());
iocanel
  • 570
  • 2
  • 2
  • Here, the output and error streams are whatever reading streams I'd wish for? – M. Mitchley Sep 15 '17 at 13:12
  • Yes, the only difference is that with your approach you are reading at your pace / polling while with the suggested code the output will be written to the buffer. – iocanel Sep 15 '17 at 15:39