1.背景
最近项目上需要远程链接至Linxu服务器执行语句,所以自己研究了下,找到了几个开源框架,并且稍微封装了一个Util类,供大家参考。
2.准备工作
Pom文件引入依赖
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
<dependency>
<groupId>com.github.cverges</groupId>
<artifactId>expect4j</artifactId>
<version>1.9</version>
</dependency>
3.工具类分享
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import expect4j.Expect4j;
import expect4j.matches.EofMatch;
import expect4j.matches.Match;
import expect4j.matches.RegExpMatch;
import expect4j.matches.TimeoutMatch;
import org.apache.oro.text.regex.MalformedPatternException;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
/**
* 执行shell语句工具类
*/
@Component
public class CMDUtilShell {
private static final int COMMAND_EXECUTION_SUCCESS_OPCODE = -2;
private static final String BACKSLASH_R = "\r";
/**
* 执行配置命令
* @param commands 要执行的命令,为字符数组
* @return 执行是否成功
*/
public String executeCommands(String[] commands, String ip, int port, String user, String password, Integer sshTimeout) {
Session session = null;
ChannelShell channel = null;
Expect4j expect = null;
try {
session = new JSch().getSession(user, ip, port);
session.setPassword(password);
session.setConfig(bulidConfig());
// 设置不提示输入密码、不显示登入信息等
session.setUserInfo(new LocalUserInfo());
session.connect();
channel = (ChannelShell) session.openChannel("shell");
expect = new Expect4j(channel.getInputStream(), channel.getOutputStream());
channel.connect(sshTimeout + 1000);
// 存放返回值
StringBuffer buffer = new StringBuffer();
// 执行语句
List<Match> lstPattern = bulidPattern(buffer, sshTimeout);
for (String strCmd : commands) {
if (expect.expect(lstPattern) != COMMAND_EXECUTION_SUCCESS_OPCODE) {
expect.send(strCmd);
expect.send(BACKSLASH_R);
}
}
expect.expect(lstPattern);
return buffer.toString().toLowerCase();
} catch (Exception ex) {
String errorMsg = String.format("[@CMDUtilShell] host=[%s] user=[%s] [error=%s]", ip, user, ex.getMessage());
} finally {
if (expect != null) {
expect.close();
}
if (channel != null) {
channel.disconnect();
}
if (session != null) {
session.disconnect();
}
}
}
/**
* 构建配置项
*/
private Hashtable<String, String> bulidConfig() {
Hashtable<String, String> config = new Hashtable<>();
config.put("userauth.gssapi-with-mic", "no");
config.put("StrictHostKeyChecking", "no");
return config;
}
/**
* 构建模式
*/
private List<Match> bulidPattern(StringBuffer buffer, Integer sshTimeout) throws MalformedPatternException {
List<Match> lstPattern = new ArrayList<>();
// 终止符
// todo:存入数据库使用参数配置
String[] regEx = {"~]#", "~#", ":~#",};
for (String regexElement : regEx) {
RegExpMatch mat = new RegExpMatch(regexElement, x -> {
buffer.append(x.getBuffer());
});
lstPattern.add(mat);
}
lstPattern.add(new EofMatch(x -> {
}));
// 设置超时时间
lstPattern.add(new TimeoutMatch(sshTimeout, x -> {
}));
return lstPattern;
}
}