前言
受2020年初的新型肺炎病毒影响,多日宅在家中无聊至极,就在琢磨一套调度系统,想用来管理维护大数据调度作业。
写了一多半停下来整改BUG,发现切换主机环境后,发现之前写的远程shell执行引擎失灵,怎么调试作业都提不到application上(之前在公司的环境下是能够正常提交的)无奈之下只能重新寻找实现方案,现总结出一套完整的解决方案,集中模板配置,可实现向多主机发送shell远程命令,较之前的实现方案当真是简便了许多,这里做一下分享。
pom依赖支持
博主选用的编程框架为SpringBoot,这里假设我们需要向两台机器发送shell远程命令,先向pom.xml添加依赖:
<!-- @ConfigurationProperties注解支持 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- shell认证支持 -->
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
配置yml
向application.yml添加信息:
jackroy1:
host: 172.26.20.80
port: 22
user: root
password: jack_roy1
jackroy2:
host: 172.26.20.81
port: 22
user: root
password: jack_roy2
# 根据需要还可设置多台主机信息
建类
创建第一台linux实体类CentOSOneEntity :
package com.jackroy.www.entity;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@Component
@ConfigurationProperties(prefix="jackroy1")
public class CentOSOneEntity {
/* 主机(IP) */
private String host;
/* 连接端口 */
private int port;
/* 编码 */
private Charset charset = StandardCharsets.UTF_8;
/* 用户 */
private String user;
/* 密码 */
private String password;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public Charset getCharset() {
return charset;
}
public void setCharset(Charset charset) {
this.charset = charset;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
创建第二台linux实体类CentOSTwoEntity :
package com.jackroy.www.entity;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
@Component
@ConfigurationProperties(prefix="jackroy2")
public class CentOSTwoEntity {
/* 主机(IP) */
private String host;
/* 连接端口 */
private int port;
/* 编码 */
private Charset charset = StandardCharsets.UTF_8;
/* 用户 */
private String user;
/* 密码 */
private String password;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public Charset getCharset() {
return charset;
}
public void setCharset(Charset charset) {
this.charset = charset;
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
根据需要还可以创建更多的主机实体类,再创建登录、执行类SSHRegister :
package com.jackroy.www.entity;
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
public class SSHRegisterEntity {
/* 连接器 */
private Connection connect;
/* 主机(IP) */
private String host;
/* 连接端口 */
private int port;
/* 编码 */
private Charset charset;
/* 用户 */
private String user;
/* 密码 */
private String password;
public SSHRegisterEntity(CentOSEntity centOSEntity) {
this.host = centOSEntity.getHost();
this.port=centOSEntity.getPort();
this.user = centOSEntity.getUser();
this.charset = centOSEntity.getCharset();
this.password = centOSEntity.getPassword();
}
/**
* 登录Centos主机
*/
private boolean login() {
connect = new Connection(host,port);
try {
connect.connect();
return connect.authenticateWithPassword(user, password);
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
/**
* 获取返回信息
*/
public StringBuilder processStdout(InputStream in) {
byte[] buf = new byte[1024];
StringBuilder builder = new StringBuilder();
try {
int length;
while ((length = in.read(buf)) != -1) {
builder.append(new String(buf, 0, length));
}
} catch (IOException e) {
e.printStackTrace();
}
return builder;
}
/**
* exec shell命令
*/
public StringBuilder exec(String shell) throws IOException {
InputStream inputStream = null;
StringBuilder result = new StringBuilder();
try {
// 认证登录信息
if (this.login()) {
// 登陆成功则打开一个会话
Session session = connect.openSession();
session.execCommand(shell);
inputStream = session.getStdout();
result = this.processStdout(inputStream);
connect.close();
}
} finally {
if (null != inputStream) {
inputStream.close();
}
}
return result;
}
}
调用
调用方法如下:
@Autowired
CentOSOneEntity centOSOneEntity;
@Autowired
CentOSTwoEntity centOSTwoEntity;
public int submit() throws IOException {
// 主机1
SSHRegisterEntity sshRegisterEntity1 = new SSHRegisterEntity(centOSOneEntity);
// 主机2
SSHRegisterEntity sshRegisterEntity2 = new SSHRegisterEntity(centOSTwoEntity);
// 向主机1发送命令
StringBuilder stringBuilder1 = sshRegisterEntity1.exec("ll /root/");
// 向主机2发送命令
StringBuilder stringBuilder2 = sshRegisterEntity2.exec("ll /root/");
// 返回信息1
System.out.println(stringBuilder1.toString());
// 返回信息2
System.out.println(stringBuilder2.toString());
return null;
}
后记
根据需要,配置多台机器灵活使用,大家在操作的时候有什么问题,可以下方留言交流。