Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Java

Remote interactive SSH command in Java

1.73/5 (6 votes)
18 Dec 2009CPOL3 min read 45.4K   45  
Implement an interactive SSH command in Java.

Introduction

This article presents a way to implement a remote connection to a server via SSH (secure shell) and to execute an interactive command through a pseudo terminal in Java.

Background

Programs which implement a remote connection to a server to execute a command via SSH (secure shell) in Java are very common, but most of them can only execute the "exec" command (non interactive cmd, in other words, execute command and hand over the control as soon as the cmd is finished, such as "date" to display the current time, and can not execute "ls' to display the file list under a designated directory (opt/3com/VCX/vcxdata/). This article will show a way to execute those commands, and further, interactive commands (such as "su root", which will claim the password, and we will input the password according to the output we get in real time).

Using the Code

First, import an external jar package sshtools. Then, declare an instance of SshClient and SessionChannelClient. You may have noticed that the way to get session output is a little different. We do not declare an object of ChannelOutputStream; instead, an object of SessionOutputReader, a point to which I will return.

Java
import com.sshtools.j2ssh.SshClient;
import com.sshtools.j2ssh.authentication.PasswordAuthenticationClient;
import com.sshtools.j2ssh.session.SessionChannelClient;
import com.sshtools.j2ssh.session.SessionOutputReader;
import com.sshtools.j2ssh.transport.IgnoreHostKeyVerification;

As we are going to login to the 3com VCX server through SSH, the server IP, user name, and password are required, and set as shown below:

Java
final private String username = "root";
final private String password = "pvadmin";
final private String hostname = "172.31.50.102";
private int outputPos = 0 ;

After executing the command, we get the output as a string. The previous output will be included in the current string to avoid the output being displayed over and over. We set outputPos as the offset from where the output will be displayed.

Java
ssh = new SshClient();
try{
    ssh.connect(hostname, new IgnoreHostKeyVerification());

Create an SSH client to connect to server via SSH, and ignore the host key verification.

Java
PasswordAuthenticationClient pwd = new PasswordAuthenticationClient();
pwd.setUsername(username);
pwd.setPassword(password);
int result = ssh.authenticate(pwd);

The result must be 4; otherwise, it means the SSH connection is not set up properly.

Java
if (result == 4)
{
   logCat.info("Connected to host");
   session = ssh.openSessionChannel();
   sor = new SessionOutputReader(session);

Open a session channel after connecting to the server successfully, and create an instance of the session output reader of the session.

Java
if (session.requestPseudoTerminal("gogrid",80,24, 0 , 0, ""))

Create a pseudo terminal to connect to the server. The terminal type could be dumb, xterm, gogrid, vt100, vt220, vt320 etc., but I strongly recommend to choose "gogrid", for the others will result in confusing characters.

Here is the the prototype of the requested pseudo terminal:

Java
boolean requestPseudoTerminal(String term, int cols, 
          int rows, int width, int height, String modes)

if (session.startShell())
{
    in = (session.getInputStream());
    logCat.info(in);
    out = session.getOutputStream();
    out.write("cd opt/3com/vcx/vcxdata/\n".getBytes());
    out.write("ls\n".getBytes());

If it succeeds in starting the shell, execute the following command: "cd /opt/3com/vcx/vcxdata/". Then, "ls" to display the file list under that directory.

Java
Thread.currentThread().sleep(1000*2);
String answer = null;
String aux = null;
aux = sor.getOutput();   
answer = aux.substring(outputPos);
outputPos = aux.length();
logCat.info(answer);

After executing the command, check the output.

Similarly, we can execute interactive commands according to the last output prompt of the server in real time. For example, we get the cworks privilege, then we want to get back to the root privilege using the "su root" command, and the password prompt will be claimed. We check the output, and when we get the password prompt, we input the password.

Java
out.write("su cworks\n".getBytes()); // input command su cworks 
out.write("su root\n".getBytes());
//  then input command su root which will claim password

Thread.currentThread().sleep(1000*2);
//verify what we have got  
String answer = null;
String aux = null;
aux = sor.getOutput(); // get the output in real time 
answer = aux.substring(outputPos);
outputPos = aux.length();
logCat.info(answer);
String str[] = answer.split("\n");
String prompt = str[str.length-1];   // get the last prompt
prompt = prompt.trim();
if (prompt.contains("Password:"))
// if the last prompt is "password 
{
   // then we input password.
   out.write("pvadmin\n".getBytes());
}

And again, check what we have got this time:

Java
Thread.currentThread().sleep(1000*2);
aux = sor.getOutput();        
answer = aux.substring(outputPos);
logCat.info(answer);

Thanks to SessionOutputReader, we can read the output stream of the session in real time. So, we can decide what command we should input according to the output prompt of the server, which is the very essence of being interactive.

Points of Interest

I will be glad if this is helpful to you. And thank you for your advice, which helped me make this article better.

Reference: http://upcommons.upc.edu/pfc/bitstream/2099.1/3790/1/53848-1.pdf.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)