前言
受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;
}
後記
根據需要,配置多臺機器靈活使用,大家在操作的時候有什麼問題,可以下方留言交流。