前段时间遇到个业务需求,定时执行shell脚本任务,这就需要在Java代码里连接到远程服务器并执行成功,在网上找了一些资料,无奈代码都不全,只能自己写了。
下面展示一些 内联代码片
。
//工具类maven坐标
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.7.7version>
dependency>
public class ExecShellUtil {
/**
* 执行脚本
*
* @param user 用户名
* @param host IP地址
* @param port 端口号
* @param commands 脚本数据
* @param password 密码
* @param preKey 密钥
* @return
* @author fengdf
*/
public static void exec(String user, String host, int port, String[] commands,String password,String preKey) {
JSch jsch = new JSch();
Session session = null;
try {
//1.创建session
session = JschUtil.createSession(jsch, shellData.getHost(), Integer.parseInt(shellData.getPort()), shellData.getUser());
//密码登录
if (){
session.setPassword(password);
log.info("密码登录:{}",password));
}else {
//2.添加密钥preKey登录
jsch.addIdentity(null,preKey.getBytes(),null,null);
}
//3.连接
session.connect();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//exec()可以通过outputStream拿到执行shell失败时的返回提示
String execResult = JschUtil.exec(session, commands, CharsetUtil.CHARSET_UTF_8, outputStream);
//执行失败时execResult返回null
if (StrUtil.isEmpty(execResult)){
//4.打印错误日志
log.info("err:{}",outputStream.toString("UTF-8"));
}else {
log.info("success:{}",execResult);
}
} catch (Exception e) {
//设置执行失败的响应内容
result.setResponseBody(e.getMessage());
log.error("shell脚本异常:{}", shellData.getShellContent());
log.error("发送请求异常", e);
} finally {
JschUtil.close(session);
}
return;
}
}
JschUtil底层用了流的方式处理日志,synchronized解决并发问题,如果有兴趣也可以自己写。
这里我遇到一个坑,同时发送两个shell命令,会有一个报:session is down
原因是我把session设成了static属性,果然写代码是要严谨认真一点!
数据表里的fieldserver_private_key_json
是longtext类型,插入值如下,
{
"name":"",
"preKey":"",
"pubKey":"",
"passhrase":""
}
entity里对应的如果是对象类型,解析时会报错,最好写成String类型
@TableField("server_private_key_json")
private String serverPrivateKeyJson;
再用XXX keyJson = JSON.parseObject(data, xxx.class);
解析即可
当然解析时可能还会报错,具体问题具体分析。
String keyJson = shellData.getServerPrivateKeyJson().replace("},", "}");
我这里多出一个逗号
当然我还是个小菜鸡,哪里有不对的地方欢迎各位大佬指正。