JSch(Java Secure Channel)是SSH2的一个纯Java实现。它允许你连接到一个sshd 服务器,进而使用端口转发,X11转发,文件传输等等功能。在前面的博客里,有介绍到如何使用JSch实现SFTP的相关操作,本文这里主要介绍如何利用JSch进行远程Shell操作。
软硬件环境说明:Windows10、IntelliJ IDEA、SpringBoot 2.1.4.RELEASE、CentOS7。
准备工作:在pom.xml中引入JSch依赖
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
编写执行Shell指令的工具类:
import com.jcraft.jsch.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Properties;
/**
* 执行Shell工具类
*
* @author JustryDeng
* @date 2019/4/29 16:29
*/
public class ExecuteShellUtil {
private static final Logger LOGGER = LoggerFactory.getLogger(ExecuteShellUtil.class);
/** 未调用初始化方法 错误提示信息 */
private static final String DONOT_INIT_ERROR_MSG = "please invoke init(...) first!";
private Session session;
private Channel channel;
private ChannelExec channelExec;
private ExecuteShellUtil() {
}
/**
* 获取ExecuteShellUtil类实例对象
*
* @return 实例
* @date 2019/4/29 16:58
*/
public static ExecuteShellUtil getInstance() {
return new ExecuteShellUtil();
}
/**
* 初始化
*
* @param ip
* 远程Linux地址
* @param port
* 端口
* @param username
* 用户名
* @param password
* 密码
* @throws JSchException
* JSch异常
* @date 2019/3/15 12:41
*/
public void init(String ip, Integer port, String username, String password) throws JSchException {
JSch jsch = new JSch();
jsch.getSession(username, ip, port);
session = jsch.getSession(username, ip, port);
session.setPassword(password);
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
session.setConfig(sshConfig);
session.connect(60 * 1000);
LOGGER.info("Session connected!");
// 打开执行shell指令的通道
channel = session.openChannel("exec");
channelExec = (ChannelExec) channel;
}
/**
* 执行一条命令
*/
public String execCmd(String command) throws Exception {
if (session == null || channel == null || channelExec == null) {
throw new Exception(DONOT_INIT_ERROR_MSG);
}
LOGGER.info("execCmd command - > {}", command);
channelExec.setCommand(command);
channel.setInputStream(null);
channelExec.setErrStream(System.err);
channel.connect();
StringBuilder sb = new StringBuilder(16);
try (InputStream in = channelExec.getInputStream();
InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(isr)) {
String buffer;
while ((buffer = reader.readLine()) != null) {
sb.append("\n").append(buffer);
}
// 释放资源
close();
LOGGER.info("execCmd result - > {}", sb);
return sb.toString();
}
}
/**
* 释放资源
*
* @date 2019/3/15 12:47
*/
private void close() {
if (channelExec != null && channelExec.isConnected()) {
channelExec.disconnect();
}
if (channel != null && channel.isConnected()) {
channel.disconnect();
}
if (session != null && session.isConnected()) {
session.disconnect();
}
}
}
测试一下:
测试一:
控制台输出:
测试二:
控制台输出:
由此可见,远程执行shell指令的工具类编写成功!
扫描二维码关注公众号,回复:
6071520 查看本文章
注:不仅能执行上面示例的shell,还能执行cp、mv等等等等指令,这里就不再一一示例了。
注:如果要执行多个指令,可以多次调用工具类,也可以像使用多指令shell一样,使用【;】或【&&】等符
号将多个指令隔开。
追注:1、【;】隔开的多个shell命令,会按照顺序执行下来,但是不能保证每条命令都执行成功。
2、【&&】隔开的多个shell命令,前面的命令执行成功,才会执行后面的命令,否则后面的命令
不执行。
3、将多指令隔开的符号,上面给出的只是最常用的两种,更多功能的符号可自行查阅相关资料。
如: