java SSH2远程登录Linux服务执行命令
前一段时间工作中用到了java远程调用Linux服务器,执行相关命令,因为比较常用,故此,在博客中记录下来。其中用到了ganymed-ssh2这个jar包,可以在http://www.ganymed.ethz.ch/ssh2/找到相关jar,不过这个jar目前好像已经停止维护了,还有一点是,这个jar,我在阿里的maven仓库中未找到。
好了,下面我们来贴下代码
/**
*
*/
package com.neusoft.mid.cloong.web.page.inspect.ssh;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import ch.ethz.ssh2.ChannelCondition;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import com.neusoft.mid.iamp.logger.LogService;
public class SSHConnect {
private static LogService log = LogService.getLogger(SSHConnect.class);
private static final int TIMEOUT = 2000;
private static final int RECONNECT_TIMES = 20;
private String userName;
private String host;
private String pass;
private int port;
private int sleepTime;
private int waitTime;
public Session openConnection() throws Exception {
Connection connection = connect(host, port, TIMEOUT);
if (!connection.authenticateWithPassword(userName, pass)) {
throw new Exception("用户名密码错误");
}
log.info("登陆成功!");
Session session = connection.openSession();
session.requestPTY("");
session.startShell();
return session;
}
private Connection connect(String address, int port, long timeOut) {
Connection conn = new Connection(address, port);
int connectTimes = 1;
long waitTime = System.currentTimeMillis() + timeOut;
do {
try {
conn.connect();
break;
} catch (IOException e) {
log.error(null, "ssh连接到主机时出错", e);
connectTimes++;
}
} while (System.currentTimeMillis() < waitTime
&& RECONNECT_TIMES <= connectTimes);
return conn;
}
public InputStream executeCommand(String command, Session session)
throws Exception {
if (command.equals("")) {
log.info("执行空指令");
return null;
}
PrintWriter out = null;
try {
out = new PrintWriter(new OutputStreamWriter(session.getStdin(),
"UTF-8"));
out.println(command);
out.flush();
return handleBufferStr(session);
} finally {
if (null != out) {
out.close();
}
}
}
/**
* 处理接收的缓存数据
*/
protected InputStream handleBufferStr(Session session) throws Exception {
ByteArrayOutputStream sb = new ByteArrayOutputStream();
ByteArrayOutputStream ersb = new ByteArrayOutputStream();
InputStream in = null;
try {
if (sleepTime == 0) {
return null;
}
Thread.sleep(sleepTime);
in = receiveMsg(sb, ersb, session);
return in;
} finally {
if (null != in) {
in.close();
}
}
}
/**
* 接收shell返回信息
*
* @param stdNormal
* @param stdError
* @return
* @throws Exception
*/
protected InputStream receiveMsg(ByteArrayOutputStream stdNormal,
ByteArrayOutputStream stdError, Session session) throws Exception {
InputStream stdout = null;
try {
stdout = session.getStdout();
// InputStream stderr = session.getStderr();
int conditions = session.waitForCondition(
ChannelCondition.STDOUT_DATA | ChannelCondition.STDERR_DATA
| ChannelCondition.EOF, waitTime);
if ((conditions & ChannelCondition.TIMEOUT) != 0) {
log.error(null, "获取session数据超时");
throw new IOException("获取打印数据超时");
}
if ((conditions & ChannelCondition.EOF) != 0) {
log.error(null, "无数据可读");
}
while (stdout.available() > 0) {
return stdout;
/*
* byte[] buffer = new byte[8192]; int len =
* stdout.read(buffer); if (len > 0) { // this check is somewhat
* paranoid if (log.isDebugEnable()) { //
* log.debug("Receive msg :" + buffer); }
* stdNormal.write(buffer, 0, len); }
*/
}
/*
* while (stderr.available() > 0) { byte[] buffer = new byte[8192];
* int len = stderr.read(buffer); if (len > 0) {// this check is
* somewhat paranoid if (log.isDebugEnable()) { //
* log.debug("Receive error msg :" + buffer); }
* stdError.write(buffer, 0, len); } }
*/
} finally {
if (null != stdout) {
stdout.close();
}
}
return null;
}
}
代码框架比较老,用的是struts,我把get/set相关删掉了,main方法懒得写了,其中先调用openConnection方法,然后调用executeCommand方法就可以获得相关返回结果。
特别要注意的是Thread.sleep(sleepTime);
这行代码。这行代码让线程睡一段时间是为了等待Linux返回结果,如果不睡,或者睡的时间比较短,会出现无法获取结果,或结果获取不全的情况。具体时间可以去Linux执行相关命令计算需要睡的时间。
总结
其中这个jar还可以实现端口转发,反向代理,等相关功能,等后续再继续添加吧。另外,相关实现ssh2相关功能的jar还有很多,比如jsch等,大家有空可以研究学习下,后续可以一起交流下经验。