Run Commands continuously and step by step based on previous command output in JSch
after 1 month struggling with code and documentation i've found the answer.
i wanted to implement the ssh in enterprise application.first of all i have to say if you want interactive behavior you should use "shell" because it can give your command and return answer and stay connect with server but "exec" after execute command close channel.then i defined output and input as class variables.this is my class:
@Service
public class SshService {
private Channel channel;
private Session session;
ByteArrayOutputStream responseStream = new ByteArrayOutputStream();
PipedInputStream pip = new PipedInputStream(40);
PipedOutputStream pop = new PipedOutputStream(pip);
PrintStream print = new PrintStream(pop);
public SshService() throws IOException {
}
public String sshConnectToOlt(String username, String password, String host, int port) throws Exception {
session = new JSch().getSession(username, host, port);
session.setPassword(password);
session.setConfig("StrictHostKeyChecking", "no");
session.connect(30000);
channel = session.openChannel("shell");
channel.setInputStream(pip);
responseStream= new ByteArrayOutputStream();
channel.setOutputStream(responseStream);
channel.connect(3 * 1000);
Thread.sleep(2000);
return responseStream.toString();
}
public String sshToOltCommands(String command) throws Exception {
print.println(command);
Thread.sleep(2000);
String response = responseStream.toString();
return response.replaceAll("\u001B\\[[\\d;]*[^\\d;]","");
}
public void disconnectFromOlt() {
this.channel.disconnect();
this.session.disconnect();
}
}
i write 3 methods.
sshConnectToOlt: for connecting to server
sshToOltCommands : executes command on server
disconnectFromOlt : disconnect from server
NOTICE:
i used
response.replaceAll("\u001B\\[[\\d;]*[^\\d;]","");
to remove ANSI control chars (VT100) from response
Ssh with JSch to a remote machine that asks twice for username and password
Your ssh
commands starts a shell session. The prompts for the credentials are just regular I/O prompts, as any other. Nothing credentials-specific. So you should provide the input the way, you would provide any other input – by writing it to the shell input stream.
starting remote (SSH) Java application with shell script will not return local prompt
You can redirect the standard input, output, and error for the java process so that its standard input, output, and error are't connected to the remote SSH server:
java ... < /dev/null > /dev/null 2>&1 &
That should permit the remote server to terminate the SSH session immediately.
When you ask the remote SSH server to invoke a command, and you don't request a TTY for that command, the server will create a set of pipes for the standard input, output, and error for the child process. The current behavior of the OpenSSH server seems to be not to close the session when the remote command exits. Instead, the server closes the session when it detects an end-of-file condition on the pipe handling standard output from the remote process.
The java process launched by your remote command is inheriting the pipes to the SSH server as its standard input etc. The SSH server doesn't get an EOF indication on these pipes because there's still a process with access to the pipes.
You can test this by running a command like like:
ssh localhost 'sleep 10 < /dev/null > /dev/null &'
If ssh exits right away without waiting for the sleep
to complete, that means you've gotten the remote SSH server not to wait on the sleep.
My own tests suggest that the SSH server is looking at the pipe receiving standard output from the child process, so that's all that you have to redirect. But you should consider redirecting all three pipes--standard input, output, and error--in case the behavior of the SSH server changes in the future.
Telnet commands into (through, inside) SSH session
I debugged your example and in my case, I needed to wait for the program, which you connect via telnet, until it is ready to receive a command.
In the second step, you can send your command and the exit command to stop the telnet, so you are reading from the stream until it has stopped by saying "Connection closed...". Be aware, that exiting from telnet can have different commands, some use quit
, some other use exit
or only wait for a termination signal.
class Telnet {
public String runCommand(Session session, String command) throws Exception {
Channel channel = session.openChannel("shell");
channel.connect(3000);
DataOutputStream outputStream = new DataOutputStream(channel.getOutputStream());
outputStream.writeBytes("telnet localhost 16379\r\n");
outputStream.flush();
DataInputStream inputStream = new DataInputStream(channel.getInputStream());
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
channel.setInputStream(inputStream, true);
// Read until we are ready to write
String line;
while (!(line= reader.readLine()).equals("Escape character is '^]'.")){
System.out.println(line);
}
// write command and exit telnet
outputStream.writeBytes(command + "\r\n");
outputStream.writeBytes("quit\r\n");
outputStream.flush();
// read until telnet has closed
String result = "";
while (!(line= reader.readLine()).equals("Connection closed by foreign host.")){
result += line +"\n";
}
outputStream.close();
inputStream.close();
channel.disconnect();
session.disconnect();
return result;
}
}
In the end, there are alternative ways to communicate without telnet, i.e. local port forwarding.
How to run SSH commands on remote system through java program (followup)
I had used a library JSch, but I guess sshxcute looks better as I went through the documentation.
Related Topics
How to Calculate the Number of Days in a Period
Java.Lang.Classnotfoundexception: Org.Springframework.Boot.Springapplication Maven
How to Convert a Hexadecimal String to Long in Java
In Java, When I Call Outputstream.Close() Do I Always Need to Call Outputstream.Flush() Before
Print Full Call Stack on Printstacktrace()
How to Cast an Object to an Int
How to Get an Enum Based on the Value of Its Field
JSON Gson.Fromjson Java Objects
Extract Source Code from .Jar File
Htmlunit Doesn't Wait for JavaScript
How to Format a Number 0..9 to Display with 2 Digits (It's Not a Date)
How to Modify JSONnode in Java
What Is the Shortest Way to Pretty Print a Org.W3C.Dom.Document to Stdout
On-The-Fly, In-Memory Java Code Compilation for Java 5 and Java 6
Java Static Serialization Rules