Providing Input/Subcommands to Command Executed Over Ssh with Jsch

Providing input/subcommands to command executed over SSH with JSch

Calling ChannelExec.setCommand multiple times has no effect.

And even if it had, I'd guess that the 192.168.50.1 : and Config.txt are not commands, but inputs to the copy run tftp : command, aren't they?

If that's the case, you need to write them to the command input.

Something like this:

ChannelExec channel = (ChannelExec) session.openChannel("exec");
channelExec.setCommand("copy run tftp : ");
OutputStream out = channelExec.getOutputStream();
channelExec.connect();
out.write(("192.168.50.1 : \n").getBytes());
out.write(("Config.txt \n").getBytes());
out.flush();

In general, it's always better to check if the command has better "API" than feeding the commands to input. Commands usually have command-line arguments/switches that serve the desired purpose better.


A related question: Provide inputs to individual prompts separately with JSch.

Providing input/subcommands to command executed over SSH with JSch Using JSF

You didn't provide us any information, that we can use to debug your problem. "it doesn't work" is not a problem description.


Anyway, one obvious problem is, that you have removed the code that reads the command output and you have not replaced it with other way to wait for the command to finish. So it's quite possible that the connection is simply terminated before the commands finishes, killing the command with it.

Wait for the channel to be closed, before you close the session:

while (!channelExec.isClosed()) Thread.sleep(100);

Or keep your command output stream reading code from your original question (you do not have to pass the output anywhere):

InputStream in = channelExec.getInputStream();

// ...

BufferedReader reader = new BufferedReader(new InputStreamReader(in));
String line;
while ((line = reader.readLine()) != null)
{
}

session.disconnect();

Provide multiple lines of input to command executed on SSH server with JSch

Bash syntax for providing two lines of an input to a command is:

( echo input1 && echo input2 ) | command

See also Pipe multiple commands into a single command.


You can also provide the input in your Java code rather than using shell constructs:

Providing input/subcommands to command executed over SSH with JSch

Provide inputs to individual prompts separately with JSch

If I understand your question correctly, it looks like the password is provided too quickly and the way the server is implemented, it discards the input that comes too early (before a prompt).

You may need to wait before sending the password.

channel.connect();
OutputStream out = channel.getOutputStream();
out.write(("username2\n").getBytes());
out.flush();
Thread.sleep(1000);
out.write(("password2\n").getBytes());
out.flush();

A more advanced solution would be to implement an Expect-like functionality.

Efficiently execute multiple commands that depend on another long running command on Unix host with JSch

What you have now is the correct way.

If you really really need to optimize it, you have to feed the commands to a remote shell session. Either start a shell explicitly using the "exec" channel. Or use "shell" channel directly. And then write the individual commands to the shell input.

See also:

  • Providing input/subcommands to command executed over SSH with JSch
  • What is the difference between the 'shell' channel and the 'exec' channel in JSch
  • Multiple commands through JSch shell
  • JSch Shell channel execute commands one by one testing result before proceeding

Obligatory warning: Do not use StrictHostKeyChecking=no to blindly accept all host keys. That is a security flaw. You lose a protection against MITM attacks. For the correct (and secure) approach, see: How to resolve Java UnknownHostKey, while using JSch SFTP library?

Unable execute sftp sub commands using jsch

Move the line

channelExec.connect();

above this block :

 OutputStream out = channelExec.getOutputStream();
out.write(("cd /xx.yy/zz \n").getBytes());
out.write(("ls \n").getBytes());
out.flush();

Thereby you first establish the connection and then fetch the Output stream.

Change System.in and read System.out programmly on the fly (Jsch)

Thanks to the comments from Martin Prikryl I found a solution.
I created a little example with Telnet instead of my real application. The basics are the same and i think it is more helpfull because more people can try it out and play with it when it is not based on a specific software.

import com.jcraft.jsch.*;
import java.io.*;

public class Main {
public static void main(String[] args) {
OutputStream out = null;
Session session = null;
try {
JSch jsch = new JSch();
String user = "sshuser";
String host = "localhost";
session = jsch.getSession(user, host, 22);
String passwd = "password";
session.setPassword(passwd);
session.setConfig("StrictHostKeyChecking", "no");

// vars and objects used later
String lineSeperator = System.getProperty("line.separator");
StringBuilder sb = new StringBuilder();
Main main = new Main();

//session.connect();
session.connect(30000); // making a connection with timeout.
ChannelExec channel = (ChannelExec) session.openChannel("exec");
InputStream in = channel.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));

// start telnet session
channel.setCommand("telnet 192.168.222.128 -l sshuser");
out = channel.getOutputStream();
channel.connect();
// wait a little bit for telnet to be ready to take the input
Thread.sleep(500);
// pass the password
out.write(("password\n").getBytes());
out.write(("\n").getBytes());
Thread.sleep(500);
// flush reader, very important!
out.flush();

// Read from Bufferreader until the current line contains a specific string
// For my real application it would be "--- END", for this example i
// used something from the last line my machine returns. Very important that this string
// appears on every possible output, or you will stuck in a while loop!
//
// Tried it with while((reader.readline())!=null) but this ends in a infinity loop too.
// Since in my application there is an String that always get returned i didn't look it further up
String responeFromLogin = main.readOutput("security updates.", reader, lineSeperator, sb);

// Working with the response, in this example a simple fail-->Exception, success --> progress
if (responeFromLogin.contains("Login incorrect")) {
throw new Exception("Failed: Login");
}
System.out.println("Login Successfull");

// Log in was successful, so lets do the next command, basiclly the same routine again
out.write(("dir\n").getBytes());
Thread.sleep(500);
out.flush();
// Again, not bulletproofed in this example
String responseFromHelp = main.readOutput("examples.desktop", reader, lineSeperator, sb);
if (!responseFromHelp.contains("test")) {
throw new Exception("Failed: Help");
}
System.out.println("Folder Found");

} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (JSchException e1) {
e1.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
} finally {
try {
if (out != null) {
out.flush();
}
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("_________________________");
System.out.println("I am done");
if (session != null) {
session.disconnect();
}
}
}

public String readOutput(String endString, BufferedReader reader, String lineSeperator, StringBuilder sb) {
String line;
String returnString = "Error";

while (true) {
try {
line = reader.readLine();
if (line.contains(endString)) {
sb.append(line).append(lineSeperator);
returnString = sb.toString();
break;
} else {
sb.append(line).append(lineSeperator);
}
} catch (IOException e) {
returnString = "Error";
e.printStackTrace();
}
}
return returnString;
}
}

Show results of SSH command executed with JSch in separate console/cmd window, not in IDE console

When you execute a console application in IDE (Eclipse/Netbeans/etc), IDE redirects console application output to Console view.

But if you run your application in cmd.exe it will use cmd.exe console.

And if you run your application directly (via java.exe), e.g. from Windows Run box, it will create its own console window.

That's just how console application behave. It has nothing to do with your code.

Also, here's some trick that can be used to make Eclipse not redirect console application output to Console view:
https://www.reddit.com/r/eclipse/comments/1bk7a1/how_do_i_run_programs_in_a_separate_console_window/

Invoke WLST commands with JSch

The ; can indeed by used in *nix based system to execute multiple commands in one shell command-line.

But what you are executing are not shell commands. Those are WLST commands, right? So you have to feed them to WLST.

Like this:

Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand("java -cp /.../weblogic.jar weblogic.WLST");
OutputStream out = channel.getOutputStream();
channel.connect();
out.write(("connect('weblogic'...)\n").getBytes());
out.write(("domainRuntime()\n").getBytes());
...

It's basically the same as generic Providing input/subcommands to command executed over SSH with JSch.



Related Topics



Leave a reply



Submit