Java 远程连接SSH
Class Example-Java SSH Client
远程连接SSH,执行shell command
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.rmi.UnexpectedException;
import org.apache.log4j.Logger;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
/**
* create an ssh client using username, password, host/connection IP, and port
*
*/
public class SSHClient {
private JSch jschSSH;
private String userName;
private String hostip;
private int intConnectionPort;
private String password;
private Session sesConnection;
private int timeOut;
private Channel channel = null;
private static final Logger LOG = Logger.getLogger(SSHClient.class);
private StringBuffer outputstream, errorstream = null;
private String result = null;
private String prvKey; // just for debug purposes.
/**
** initialize SSH machine config
*/
public SSHClient(String user, String passwd, String connectionIP, int port) {
jschSSH = new JSch();
userName = user;
password = passwd;
hostip = connectionIP;
intConnectionPort = port;
timeOut = 30000;
}
public SSHClient(String user, String connectionIP, int port, String prvKey) throws JSchException {
this(user, null, connectionIP, port);
if (prvKey == null) {
throw new IllegalArgumentException("prvKey must not be null");
}
jschSSH.addIdentity(prvKey);
this.prvKey = prvKey;
}
/**
** Connect to the remote SSH machine
*/
public void connect() throws JSchException {
String keyFileMessage = (prvKey == null) ? "without ssh key file."
: String.format("using ssh key file: [%s].", this.prvKey);
String passwordMessage = (this.password != null) ? ":" + this.password : "";
LOG.info(String.format("SSH connecting to: %s%s@%s:%d %s", userName, passwordMessage, hostip, intConnectionPort,
keyFileMessage));
sesConnection = jschSSH.getSession(userName, hostip, intConnectionPort);
if (this.prvKey == null) {
sesConnection.setPassword(password);
}
sesConnection.setConfig("StrictHostKeyChecking", "no");
/**
* Used to / bypass the key check
*/
sesConnection.connect(timeOut);
}
/**
* Execution of the command with execute channel on the remote machine
*
* @param command
* Actual command that needs to get executed on terminal
* @return String as method result
* @throws JSchException
* @throws IOException
*/
public String runCommand(String command) throws JSchException, IOException {
channel = sesConnection.openChannel("exec");
// ((ChannelExec) channel).setCommand("source /etc/bashrc");
((ChannelExec) channel).setCommand(command);
LOG.info("Command:" + command);
BufferedReader br = new BufferedReader(new InputStreamReader(channel.getInputStream()));
InputStream error = ((ChannelExec) channel).getErrStream();
channel.connect(60000);
outputstream = new StringBuffer();
String msg = null;
while ((msg = br.readLine()) != null) {
outputstream.append(msg).append("\n");
/**
* Enters this loop if command has executed successfully and stores
* result in output String
*/
}
LOG.info("The output stream's length is:" + outputstream.length());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
LOG.warn("After sleep 2 second got the error message:" + e.getMessage());
}
// channel.disconnect();
int code = channel.getExitStatus();
LOG.info("Channel exit status:" + channel.getExitStatus());
LOG.debug("Output of command successful execution: " + outputstream.toString());
String errormsg = null;
BufferedReader errorReader = new BufferedReader(new InputStreamReader(error));
errorstream = new StringBuffer();
while ((errormsg = errorReader.readLine()) != null) {
LOG.error("Terminal error output is: " + errormsg);
errorstream.append(errormsg).append("\n");
/**
* Enters this loop if command has not executed successfully. Used
* for printing the message displayed on the terminal.
*/
}
/*
* LOG.info("Terminal output is: "+ String.format(
* "OutputStream: [%s] \n ErrorStream: [%s]", outputstream.toString(),
* errorstream.toString())); if (channel.getExitStatus() != 0) { throw
* new IOException("Error code is " + channel.getExitStatus()); }
*/
/**
* Throw Channel exitstatus not 0 exception
*/
channel.disconnect();
// return String.format("OutputStream: [%s] \n ErrorStream: [%s]",
// outputstream.toString(), errorstream.toString());
if (errorstream.length() > 0) {
return errorstream + outputstream.toString() + "ExitCode" + code;
} else {
return outputstream.toString() + "ExitCode" + code;
}
}
/**
* Please be careful when use this method. This method will execute the
* command and disconnect immediately.So you can not get the output and the
* channel exitCode will always be -1
*
* @param command
* @return
* @throws JSchException
*/
public int runCommandWithoutWaitOutput(String command) throws JSchException {
channel = sesConnection.openChannel("exec");
((ChannelExec) channel).setCommand(command);
LOG.info("Command:" + command);
channel.connect(60000);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
int code = channel.getExitStatus();
channel.disconnect();
return code;
}
/**
* Execution of the command with shell channel on the remote machine
*
* @param command
* @return
* @throws JSchException
* @throws IOException
*/
public String runShellCommand(String command) throws JSchException, IOException {
channel = sesConnection.openChannel("shell");
OutputStream output = channel.getOutputStream();
PrintStream pstream = new PrintStream(output, true);
channel.connect();
InputStream input = channel.getInputStream();
LOG.info("SSH Shell Command:" + command);
// Execute command.
pstream.println(command);
// Exit shell manually, or will be fall into endless loop.
pstream.println("exit");
pstream.close();
result = getCommandOutput(input, channel);
// channel.disconnect();
LOG.info("Channel Exit status is: " + channel.getExitStatus());
if (channel.getExitStatus() != 0) {
LOG.info("Terminal output:\n" + result.toString());
throw new UnexpectedException("Exit Status not 0. Result:\n" + result);
}
channel.disconnect();
return result.toString();
}
/**
* Method getOutputStream() is used to get OutputStream data after executing
* the SSH command
*
* @return String outputstream if it is not null or will return null
*/
public String getOutputStream() {
if (outputstream == null) {
return null;
} else
return outputstream.toString();
}
/**
* Method getErrorStream() is used to get ErrorStream data after executing
* the SSH command
*
* @return String errorstream if it is not null or will return null
*/
public String getErrorStream() {
if (errorstream == null) {
return null;
} else
return errorstream.toString();
}
/**
* Method getShellRunOutput() is used to get shell output for data after
* executing the SSH command
*
* @return String result if it is not null or will return null
*/
public String getShellRunOutput() {
if (result == null) {
return null;
} else
return result;
}
/**
** Method returns channel exit status for the SSH connection
*
* @return int -2 if channel is null or channel exit status
*/
public int getChannelExitStatus() {
LOG.info("Channel exiting...");
if (channel == null) {
return -2;
} else
/**
* If channel.getExitStatus() = -2 it means that the channel is
* still null and there is issue in the execution of SSH. If it is 0
* it means channel command execution is completed successfully.
*/
return channel.getExitStatus();
}
/**
** Close the SSH connection
*/
public void close() {
sesConnection.disconnect();
}
/**
* Get Command execute output.
*
* @param input
* @param channel
* @throws IOException
*/
private static String getCommandOutput(InputStream input, Channel channel) throws IOException {
StringBuilder result = new StringBuilder();
int size = 1024;
byte[] bte = new byte[size];
while (true) {
while (input.available() > 0) {
int i = input.read(bte, 0, 1024);
if (i < 0)
break;
result.append(new String(bte, 0, i));
}
if (channel.isClosed()) {
if (input.available() > 0) {
int i = input.read(bte, 0, 1024);
result.append(new String(bte, 0, i));
}
break;
}
}
return result.toString();
}
public void setAuthenticationKey(String kEY_FILE_PATH) {
// TODO Auto-generated method stub
}
}