代码分享:java通过ssh执行命令

代码分享:java通过ssh执行命令

最近在使用搜狐开源的cachecloud做redis集群的管理。看了下源码,里面的通过ssh执行安装和运维命令的代码,和大家分享下。以做他山之石。

/**

* SSH 方式登录远程主机,执行命令,方法内部会关闭所有资源,调用方无须关心。

*

* @param ip 主机ip

* @param username 用户名

* @param password 密码

* @param command 要执行的命令

*/

public static String execute(String ip, int port, String username, String password,

final String command) throws SSHException {

if (StringUtil.isBlank(command)) {

return EMPTY_STRING;

}

port = IntegerUtil.defaultIfSmallerThan0(port, ConstUtils.SSH_PORT_DEFAULT);

Result rst = sshTemplate.execute(ip, port, username, password, new SSHCallback() {

public Result call(SSHSession session) {

return session.executeCommand(command);

}

});

if(rst.isSuccess()) {

return rst.getResult();

}

return "";

}

继续来看sshTemplate的execute方法

/**

* 通过回调执行命令

* @param ip

* @param port

* @param username

* @param password

* @param callback 可以使用Session执行多个命令

* @throws SSHException

*/

public Result execute(String ip, int port, String username, String password,

SSHCallback callback) throws SSHException{

Connection conn = null;

try {

conn = getConnection(ip, port, username, password);

return callback.call(new SSHSession(conn, ip+":"+port));

} catch

(Exception e) {

throw new SSHException("SSH err: " + e.getMessage(), e);

} finally {

close(conn);

}

}

可以看到,先建立连接

/**

* 获取连接并校验

* @param ip

* @param port

* @param username

* @param password

* @return Connection

* @throws Exception

*/

private Connection getConnection(String ip, int port,

String username, String password) throws Exception {

Connection conn = new Connection(ip, port);

conn.connect(null, CONNCET_TIMEOUT, CONNCET_TIMEOUT);

boolean isAuthenticated = conn.authenticateWithPassword(username, password);

if (isAuthenticated == false) {

throw new Exception("SSH authentication failed with [ userName: " +

username + ", password: " + password + "]");

}

return conn;

}

这个Connection使用的是

ch.ethz.ganymed

ganymed-ssh2

回调中是这样的

/**

* 执行命令并返回结果,可以执行多次

* @param cmd

* @param lineProcessor 回调处理行

* @return 如果lineProcessor不为null,那么永远返回Result.true

*/

public Result executeCommand(String cmd, LineProcessor lineProcessor, int timoutMillis) {

Session session = null;

try {

session = conn.openSession();

return executeCommand(session, cmd, timoutMillis, lineProcessor);

} catch (Exception e) {

logger.error("execute ip:"+conn.getHostname()+" cmd:"+cmd, e);

return new Result(e);

} finally {

close(session);

}

}

public Result executeCommand(final Session session, final String cmd,

final int timoutMillis, final LineProcessor lineProcessor) throws Exception{

Future future = taskPool.submit(new Callable() {

public Result call() throws Exception {

session.execCommand(cmd);

//如果客户端需要进行行处理,则直接进行回调

if(lineProcessor != null) {

processStream(session.getStdout(), lineProcessor);

} else {

//获取标准输出

String rst = getResult(session.getStdout());

if(rst != null) {

return new Result(true, rst);

}

//返回为null代表可能有异常,需要检测标准错误输出,以便记录日志

Result errResult = tryLogError(session.getStderr(), cmd);

if(errResult != null) {

return errResult;

}

}

return new Result(true, null);

}

});

Result rst = null;

try {

rst = future.get(timoutMillis, TimeUnit.MILLISECONDS);

future.cancel(true);

} catch (TimeoutException e) {

logger.error

("exec ip:{} {} timeout:{}", conn.getHostname(), cmd, timoutMillis);

throw new SSHException(e);

}

return rst;

}

先拿到session,然后执行传入的command


分享到:


相關文章: