1

I am very new to JSch. I am trying to run few commands on a server which I am getting as input from some other system. What I am doing is taking those commands and passing them as a parameter to a java method. For Eg:

public String readFileFromPath(String server, String path,
            String fileName);

Here first we have to cd to 'path', then we need to read some particular content from the file present on the path. To implement this I did following :

Session session = sshOperations.getSessionWithTimeout(USER,server,SSHPORT,1000);
Channel shellChannel = sshOperations.getShellChannel(session);
InputStream in = new PipedInputStream();
PipedOutputStream consoleInput = new PipedOutputStream((PipedInputStream) in);
OutputStream out = new PipedOutputStream();
BufferedReader consoleOutput = new BufferedReader(new InputStreamReader(new PipedInputStream((PipedOutputStream) out)));
shellChannel.setInputStream(in);
shellChannel.setOutputStream(out);
shellChannel.connect(1000);
consoleInput.write(("cd "+path).getBytes());

// first While
while ((line = consoleOutput.readLine()) != null)
{
    System.out.println("check "+ line);
}

// execute second command
consoleInput.write("cat some.properties".getBytes());

// second While
while ((line = consoleOutput.readLine()) != null)
{
    System.out.println("check "+ line);
}

Now what I know is whenever I connect to that server I get a welcome text :

"You are using <serverName> server. Please contact admin for any issues" So, after the first while loop my cd command ran and it prints the message mentioned above. But, after this it waits for more output from the output stream (it is stuck at this point )and the output stream can't product anything until I run another command.

Somehow I want to exit from the first while loop without writing the logic for consuming the 2 lines(fixed lines). As for the next command I will not know how many lines will come as output in stream.

Please suggest the logic to the get the desired output i.e. I ran a command and some logic consumes it and then I get get to run another command and so on until all the commands which came as parameter are executed.

Is there any other way to achive the same?

Thanks

Nicholas K
  • 15,148
  • 7
  • 31
  • 57
Ankit Chauhan
  • 646
  • 6
  • 20
  • What is the purpose of `line`? – Nicholas K Sep 18 '18 at 16:46
  • I am using `line` to get the output of command executed. In the code I am just printing the output for now but actually I have to pass it to some other system. It may be like 'Permisson denied' for `cd` command, which the code will read and say send 'You need to get permission to this folder' to system using my APIs. – Ankit Chauhan Sep 19 '18 at 04:17
  • [This answer could help you](https://stackoverflow.com/questions/8094938/transfer-files-via-sftp-using-jcraft/39250104#39250104) – Nicholas K Sep 19 '18 at 09:57

1 Answers1

0

Do not use "shell" channel. The "shell" channel is intended to implement an interactive session (hence the welcome message), not to automate command execution.

To automate command execution, use "exec" channel. See Multiple commands through JSch shell.

Though you actually do not need multiple commands. There's no need for cd. Just use a full path in the cat command

ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand("cat " + path + "/some.properties");
channel.connect();

Though actually, if you want to read contents of files, use SFTP, instead of running console commands like cat. SFTP is a standardized API to access files over SFTP.

See SFTP file transfer using Java JSch.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • Thanks for the answer. Actually what I need is to run the commands in same context(session) i.e. run a commands, process it's result and then run the next command given that previous commands executed (just like we do in ssh clients). From your answer, I understand that `exec` channel will not help me to do that and I guess I can handle that part in java. – Ankit Chauhan Sep 20 '18 at 13:09
  • To quote, below helped me : If you need to execute commands in a way that previous commands affect later commands (like changing a working directory or setting an environment variable), you have to execute all commands in the same channel. Use an appropriate construct of the server's shell for that. On most systems you can use semicolons: `execChannel.setCommand("command1 ; command2 ; command3");` – Ankit Chauhan Sep 20 '18 at 13:10
  • And this : **Most complicated situation is, when the commands depend on one another and you need to process results of previous commands before proceeding to other commands. When you have such need, it usually indicates a bad design. Think hard, if this is really the only solution to your problem. Or consider implementing a server-side shell script to implement the logic, instead of doing it remotely from Java code. Shell scripts have much more powerful techniques to check for results of previous commands, then you have with SSH interface in JSch.** – Ankit Chauhan Sep 20 '18 at 13:10
  • Still, double check that you really need to execute the *"commands in same context"* - As opposite to executing the commands one after another. - You need the same context only if the previous commands modify an environment somehow (like setting an environment variable). – Martin Prikryl Sep 20 '18 at 13:16