java 整合jsch使用 远程交互服务器
背景
java 通过jsch 远程执行命令 jsch 主要是类似Xshell 只不过是代码级别使用,而 Xshell使用界面化
jsch可以执行任何shell 脚本,但是弊端是执行一次必须要关闭当前会话,每次都要cd当前目录
在执行相关命令,都是操作 channle 同时写了一个cmd执行方法为的是执行linux命令
setCommand(…) 这个方法是比较重要的 session就是维护你当前会话和服务器进行交流的
channle相当于管道流,数据交互用的
一、导入相关的依赖包
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
二、实现相关的工具类
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@Slf4j
public class ShellUtil {
private String host;
private String username;
private String password;
private int port = 22;
private int timeout = 60 * 60 * 1000;
public ShellUtil(String host, String username, String password, int port, int timeout) {
this.host = host;
this.username = username;
this.password = password;
this.port = port;
this.timeout = timeout;
}
public ShellUtil(String host, String username, String password) {
this.host = host;
this.username = username;
this.password = password;
}
public Session createSession() throws JSchException {
JSch jSch = new JSch();
// 1. 获取 ssh session
Session session = jSch.getSession(username, host, port);
session.setPassword(password);
session.setTimeout(timeout);
//StrictHostKeyChecking=no 最不安全的级别,当然也没有那么多烦人的提示了,相对安全的内网测试时建议使用
//如果连接server的key在本地不存在,那么就自动添加到文件中(默认是known_hosts),并且给出一个警告。
//StrictHostKeyChecking=ask 默认的级别,就是出现刚才的提示了。如果连接和key不匹配,给出提示,并拒绝登录。
//StrictHostKeyChecking=yes 最安全的级别,如果连接与key不匹配,就拒绝连接,不会提示详细信息。
session.setConfig("StrictHostKeyChecking", "no");
// 获取到 ssh session
session.connect();
return session;
}
public String execCommand(String cmd) {
Session session = null;
ChannelExec channelExec = null;
BufferedReader inputStreamReader = null;
BufferedReader errInputStreamReader = null;
StringBuilder runLog = new StringBuilder("");
StringBuilder errLog = new StringBuilder("");
try {
session = createSession();
// 2. 通过 exec 方式执行 shell 命令
channelExec = (ChannelExec) session.openChannel("exec");
channelExec.setCommand(cmd);
// 执行命令
channelExec.connect();
// 3. 获取标准输入流
inputStreamReader = new BufferedReader(new
InputStreamReader(channelExec.getInputStream()));
// 4. 获取标准错误输入流
errInputStreamReader = new BufferedReader(new
InputStreamReader(channelExec.getErrStream()));
// 5. 记录命令执行 log
String line;
while ((line = inputStreamReader.readLine()) != null) {
runLog.append(line).append("\n");
}
// 6. 记录命令执行错误 log
String errLine;
while ((errLine = errInputStreamReader.readLine()) != null) {
errLog.append(errLine).append("\n");
}
// 7. 输出 shell 命令执行日志
log.info("exitStatus={},openChannel.isClosed={}", channelExec.getExitStatus(), channelExec.isClosed());
log.info("命令执行完成,执行日志如下:{}", runLog.toString());
log.info("命令执行完成,执行错误日志如下:{}", errLog.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (!StringUtils.isEmpty(inputStreamReader)) {
inputStreamReader.close();
}
if (!StringUtils.isEmpty(errInputStreamReader)) {
errInputStreamReader.close();
}
if (!StringUtils.isEmpty(channelExec)) {
channelExec.disconnect();
}
if (!StringUtils.isEmpty(session)) {
session.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return runLog.toString();
}
}
三、实现调用
String shCmd = "sh /xxx/xxx/syncFile.sh";
//执行调用脚本执行
ShellUtil shellUtil = new ShellUtil("ip", "username", "password");
String execLog = shellUtil.execCommand(shCmd);
log.info(execLog);