0

I am using JSch to run a sudo command on a remote linux server.

The example below shows an attempt to cd into a directory and return the contents. I am testing the use case where myDirectory does NOT exist.

public static List<String> executeExecCommand() {

  try {

    Session session = new JSch().getSession() // paraphrasing for brevity

    Channel channel - session.openChannel("exec");

    String command = "echo \"password\" | sudo -S bash -c \"cd myDirectory/ && ls -la \"";

    ((ChannelExec(channel).setCommand(command);
    channel.setInputStream(null);
    ((ChannelExec(channel).setErrStream(System.err);
    InputStream input = channel.getInputStream();
    channel.connect();
    List<String> output = new ArrayList<>();

    try {
        InputStreamReader inputReader = new InputStreamReader(input);
        BufferedReader bufferedReader = new BufferedReader(InputReader);
        String line = null;
        while (true) {
            while ((line = bufferedReader.readLine()) != null) {
                output.add(line);
                System.out.println("here is a line " + line);
            }
        if (channel.isClosed()( {
            if (input.available() > 0) {
                continue;
            }
            logger.DEBUG("exit status " + channel.getExitStatus());
            break;
        }
        bufferedReader.close();
        inputReader.close();
    } catch (IOException ex) {
        ex.printStackTrace();
    }

    channel.disconnect();
    session.disconnect();

    return output;

    } catch (Throwable t) {
        throw new JSchException("executeExecCommand : unable to establish SSH session " + t.toString());
    }
}

When run from a Unit Test in intelliJ I get output as follows:

.
.
[sudo] password for username : bash: line 0: cd: myDirectory/: No such file or directory

2019-01-03 10:40:18 DEBUG [main] <Filename>:<linenumber> - exit status: 1
.
.

This is to be expected, but my question is How do I programmatically access the [sudo] output line? I have looked at the ErrorStream but that does not contain the text which is output and displayed on intelliJ's output console.

Note the line System.out.println("here is a line " + line); is not executed.

Note also that that the [sudo] line is not output when run from command prompt : ie "mvn test"

So, how do I programmatically access the [sudo] output line?

mikec
  • 155
  • 1
  • 17

1 Answers1

-1

Using @MartinPrikil's solution How to read JSch command output? (But this solution has an infinite loop)

I took some of his code and added it to my code as follows: This gives me programmatic access to the error text via the variable "errorBufferedReader"

   ((ChannelExec(channel).setCommand(command);
    channel.setInputStream(null);
    ((ChannelExec(channel).setErrStream(System.err);
    InputStream input = channel.getInputStream();
    InputStream error = channel.getExtInputStream();
    channel.connect();
    List<String> output = new ArrayList<>();
    List<String> errorOutput = new ArrayList<>();

    try {
        InputStreamReader inputReader = new InputStreamReader(input);
        BufferedReader bufferedReader = new BufferedReader(inputReader);
        InputStreamReader errorReader = new InputStreamReader(error);
        BufferedReader errorBufferedReader = new BufferedReader(errorReader);
        String line = null;
        while (true) {
            while ((line = bufferedReader.readLine()) != null) {
                output.add(line);
                System.out.println("here is a line " + line);
            }
            while ((line = errorBufferedReader.readLine()) != null) {
                Output.add(line);
                System.out.println("here is an error line " + line);
            }
        if (channel.isClosed()( { etc etc }
mikec
  • 155
  • 1
  • 17
  • What *"infinite loop"*? Both your and my code ends on `channel.isClosed()`. --- And your code actually suffers the same problem as the incorrect accepted answer to the linked question. If there's too much output on the *error output* with no intermixed output on the *normal output*, your code will deadlock. Try it with command `"for((i=1;i<=10000;i+=2)); do echo \"Long error output - $i\" >&2; done"`. – Martin Prikryl Jan 08 '19 at 12:11
  • Ah. Maybe it deadlocked rather than entering an infinite loop. Sorry. – mikec Jan 09 '19 at 16:49
  • Hi Martin. The accepted solution I posted above works and exits fine. When I used code in the solution to 47554723 it hung. No error output so I assumed it was an infinite loop or deadlock. – mikec Jan 10 '19 at 11:38