How to Run Ssh Commands on Remote System Using Java

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



Leave a reply



Submit