最近在使用搜狐开源的cachecloud做redis集群的管理。看了下源码,里面的通过ssh执行安装和运维命令的代码,和大家分享下。以做他山之石。
继续来看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使用的是
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
</dependency>
回调中是这样的
/**
* 执行命令并返回结果,可以执行多次
* @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 <Result> future = taskPool.submit( new Callable<Result>() {
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