首页接口重构
This commit is contained in:
@@ -8,80 +8,59 @@ import com.jeesite.modules.apps.Module.DockerResult;
|
|||||||
import com.jeesite.modules.apps.Module.SystemInfo;
|
import com.jeesite.modules.apps.Module.SystemInfo;
|
||||||
import com.jeesite.modules.biz.entity.MySftpAccounts;
|
import com.jeesite.modules.biz.entity.MySftpAccounts;
|
||||||
import io.micrometer.common.util.StringUtils;
|
import io.micrometer.common.util.StringUtils;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class DockerUtil {
|
public class DockerUtil {
|
||||||
|
|
||||||
private static final int SSH_TIMEOUT = 10000;
|
private static final int SSH_TIMEOUT = 50000;
|
||||||
private static final Map<String, Session> sessionCache = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
private static Session getSession(MySftpAccounts account) throws Exception {
|
|
||||||
String key = account.getAccountId();
|
|
||||||
|
|
||||||
// 1. 从缓存取
|
|
||||||
Session session = sessionCache.get(key);
|
|
||||||
if (session != null && session.isConnected()) {
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. 无效则移除旧的
|
|
||||||
if (session != null) {
|
|
||||||
session.disconnect();
|
|
||||||
sessionCache.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 创建新连接
|
|
||||||
JSch jsch = new JSch();
|
|
||||||
int port = account.getHostPort() == null ? 22 : account.getHostPort();
|
|
||||||
session = jsch.getSession(account.getUsername(), account.getHostIp(), port);
|
|
||||||
session.setTimeout(SSH_TIMEOUT);
|
|
||||||
|
|
||||||
// 密钥/密码认证
|
|
||||||
if ("key".equalsIgnoreCase(account.getAuthType()) && account.getPrivateKey() != null) {
|
|
||||||
byte[] prvKey = account.getPrivateKey().getBytes(StandardCharsets.UTF_8);
|
|
||||||
jsch.addIdentity("id_" + key, prvKey, null, null);
|
|
||||||
} else {
|
|
||||||
session.setPassword(account.getPassword());
|
|
||||||
}
|
|
||||||
|
|
||||||
Properties config = new Properties();
|
|
||||||
config.put("StrictHostKeyChecking", "no");
|
|
||||||
session.setConfig(config);
|
|
||||||
session.connect(SSH_TIMEOUT);
|
|
||||||
|
|
||||||
sessionCache.put(key, session);
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ====================== 执行命令(最稳定)======================
|
|
||||||
private static String runCommand(MySftpAccounts account, String cmd) {
|
private static String runCommand(MySftpAccounts account, String cmd) {
|
||||||
|
JSch jsch = new JSch();
|
||||||
Session session = null;
|
Session session = null;
|
||||||
ChannelExec channel = null;
|
ChannelExec channel = null;
|
||||||
InputStream in = null;
|
InputStream in = null;
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
session = getSession(account);
|
int port = Optional.ofNullable(account.getHostPort()).orElse(22);
|
||||||
|
session = jsch.getSession(account.getUsername(), account.getHostIp(), port);
|
||||||
|
session.setTimeout(SSH_TIMEOUT);
|
||||||
|
|
||||||
// 拼接命令
|
// 认证
|
||||||
String command = cmd;
|
if ("key".equalsIgnoreCase(account.getAuthType()) && StringUtils.isNotBlank(account.getPrivateKey())) {
|
||||||
if (StringUtils.isNotBlank(account.getRootPath())) {
|
jsch.addIdentity(
|
||||||
command = "cd " + account.getRootPath() + " && " + cmd;
|
"tempKey",
|
||||||
|
account.getPrivateKey().getBytes(StandardCharsets.UTF_8),
|
||||||
|
null, null
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
session.setPassword(account.getPassword());
|
||||||
}
|
}
|
||||||
|
|
||||||
channel = (ChannelExec) session.openChannel("exec");
|
Properties config = new Properties();
|
||||||
channel.setCommand(command);
|
config.put("StrictHostKeyChecking", "no");
|
||||||
channel.setErrStream(System.err, true); // 把错误流也读出来
|
config.put("tcp.nodelay", "yes"); // 加速
|
||||||
in = channel.getInputStream();
|
session.setConfig(config);
|
||||||
channel.connect(SSH_TIMEOUT);
|
session.connect(SSH_TIMEOUT);
|
||||||
|
|
||||||
byte[] buf = new byte[4096];
|
// 执行命令
|
||||||
|
StringBuilder command = new StringBuilder();
|
||||||
|
if (StringUtils.isNotBlank(account.getRootPath())) {
|
||||||
|
command.append("cd ").append(account.getRootPath()).append(" && ");
|
||||||
|
}
|
||||||
|
command.append(cmd);
|
||||||
|
|
||||||
|
channel = (ChannelExec) session.openChannel("exec");
|
||||||
|
channel.setCommand(command.toString());
|
||||||
|
channel.setErrStream(System.err, true);
|
||||||
|
in = channel.getInputStream();
|
||||||
|
channel.connect();
|
||||||
|
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
int len;
|
int len;
|
||||||
while ((len = in.read(buf)) != -1) {
|
while ((len = in.read(buf)) != -1) {
|
||||||
out.write(buf, 0, len);
|
out.write(buf, 0, len);
|
||||||
@@ -90,24 +69,17 @@ public class DockerUtil {
|
|||||||
return out.toString(StandardCharsets.UTF_8).trim();
|
return out.toString(StandardCharsets.UTF_8).trim();
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// 执行失败,清理坏连接
|
|
||||||
if (session != null) {
|
|
||||||
session.disconnect();
|
|
||||||
sessionCache.remove(account.getAccountId());
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try { if (in != null) in.close(); } catch (Exception ignored) {}
|
||||||
if (in != null) in.close();
|
try { if (channel != null) channel.disconnect(); } catch (Exception ignored) {}
|
||||||
if (channel != null) channel.disconnect();
|
try { if (session != null) session.disconnect(); } catch (Exception ignored) {}
|
||||||
out.close();
|
|
||||||
} catch (Exception ignored) {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<ContainerInfo> listContainers(MySftpAccounts accounts, boolean all) {
|
public static List<ContainerInfo> listContainers(MySftpAccounts accounts, boolean all) {
|
||||||
String FORMAT = "{{.ID}}|{{.Image}}|{{.Command}}|{{.CreatedAt}}|{{.Status}}|{{.Ports}}|{{.Names}}";
|
String fmt = "{{.ID}}|{{.Image}}|{{.Command}}|{{.CreatedAt}}|{{.Status}}|{{.Ports}}|{{.Names}}";
|
||||||
String cmd = (all ? "docker ps -a" : "docker ps") + " --format \"" + FORMAT + "\"";
|
String cmd = (all ? "docker ps -a" : "docker ps") + " --format \"" + fmt + "\"";
|
||||||
String output = runCommand(accounts, cmd);
|
String output = runCommand(accounts, cmd);
|
||||||
|
|
||||||
if (output == null || output.isBlank()) {
|
if (output == null || output.isBlank()) {
|
||||||
@@ -132,6 +104,7 @@ public class DockerUtil {
|
|||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====================== 容器操作 ======================
|
||||||
public static DockerResult start(MySftpAccounts accounts, String containerId) {
|
public static DockerResult start(MySftpAccounts accounts, String containerId) {
|
||||||
String res = runCommand(accounts, "docker start " + containerId);
|
String res = runCommand(accounts, "docker start " + containerId);
|
||||||
return res != null ? DockerResult.ok(res) : DockerResult.fail("启动失败");
|
return res != null ? DockerResult.ok(res) : DockerResult.fail("启动失败");
|
||||||
@@ -162,28 +135,21 @@ public class DockerUtil {
|
|||||||
String res = runCommand(accounts, "docker inspect " + containerId);
|
String res = runCommand(accounts, "docker inspect " + containerId);
|
||||||
return res != null ? DockerResult.ok(res) : DockerResult.fail("查询详情失败");
|
return res != null ? DockerResult.ok(res) : DockerResult.fail("查询详情失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SystemInfo systemInfo(MySftpAccounts accounts) {
|
public static SystemInfo systemInfo(MySftpAccounts accounts) {
|
||||||
SystemInfo info = new SystemInfo();
|
SystemInfo info = new SystemInfo();
|
||||||
String output = runCommand(accounts,
|
String cmd =
|
||||||
"top -bn1 | grep 'Cpu(s)' | awk '{printf \"%.1f\", 100-$8}'; echo; " +
|
"top -bn1 | grep 'Cpu(s)' | awk '{printf \"%.1f\", 100-$8}'; echo ; " +
|
||||||
"free | grep Mem | awk '{printf \"%.1f\", $3/$2*100}'; echo; " +
|
"free | grep Mem | awk '{printf \"%.1f\", $3/$2*100}'; echo ; " +
|
||||||
"df -h / | grep / | awk '{gsub(/%/,\"\"); print $5}'"
|
"df -h / | grep / | awk '{gsub(/%/,\"\"); print $5}'";
|
||||||
);
|
|
||||||
|
|
||||||
|
String output = runCommand(accounts, cmd);
|
||||||
if (output == null) return info;
|
if (output == null) return info;
|
||||||
|
|
||||||
String[] lines = output.split("\\R");
|
String[] lines = output.split("\\R");
|
||||||
if (lines.length >= 1) info.setCpu(lines[0].trim());
|
if (lines.length >= 1) info.setCpu(lines[0].trim());
|
||||||
if (lines.length >= 2) info.setMemory(lines[1].trim());
|
if (lines.length >= 2) info.setMemory(lines[1].trim());
|
||||||
if (lines.length >= 3) info.setDisk(lines[2].trim());
|
if (lines.length >= 3) info.setDisk(lines[2].trim());
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
public static void closeSession(String accountId) {
|
|
||||||
Session s = sessionCache.remove(accountId);
|
|
||||||
if (s != null && s.isConnected()) s.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void closeAll() {
|
|
||||||
sessionCache.values().forEach(s -> { if (s.isConnected()) s.disconnect(); });
|
|
||||||
sessionCache.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user