From d26914b93c7b03d64d50caa2d9924744cce5833d Mon Sep 17 00:00:00 2001 From: gaoxq <376340421@qq.com> Date: Tue, 14 Apr 2026 09:08:24 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A6=96=E9=A1=B5=E6=8E=A5=E5=8F=A3=E9=87=8D?= =?UTF-8?q?=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/jeesite/modules/utils/DockerUtil.java | 126 +++++++----------- 1 file changed, 46 insertions(+), 80 deletions(-) diff --git a/web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java b/web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java index 4dcf31a..3680039 100644 --- a/web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java +++ b/web-api/src/main/java/com/jeesite/modules/utils/DockerUtil.java @@ -8,80 +8,59 @@ import com.jeesite.modules.apps.Module.DockerResult; import com.jeesite.modules.apps.Module.SystemInfo; import com.jeesite.modules.biz.entity.MySftpAccounts; import io.micrometer.common.util.StringUtils; - import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; public class DockerUtil { - private static final int SSH_TIMEOUT = 10000; - private static final Map sessionCache = new ConcurrentHashMap<>(); + private static final int SSH_TIMEOUT = 50000; - 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) { + JSch jsch = new JSch(); Session session = null; ChannelExec channel = null; InputStream in = null; ByteArrayOutputStream out = new ByteArrayOutputStream(); 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 (StringUtils.isNotBlank(account.getRootPath())) { - command = "cd " + account.getRootPath() + " && " + cmd; + // 认证 + if ("key".equalsIgnoreCase(account.getAuthType()) && StringUtils.isNotBlank(account.getPrivateKey())) { + jsch.addIdentity( + "tempKey", + account.getPrivateKey().getBytes(StandardCharsets.UTF_8), + null, null + ); + } else { + session.setPassword(account.getPassword()); } - channel = (ChannelExec) session.openChannel("exec"); - channel.setCommand(command); - channel.setErrStream(System.err, true); // 把错误流也读出来 - in = channel.getInputStream(); - channel.connect(SSH_TIMEOUT); + Properties config = new Properties(); + config.put("StrictHostKeyChecking", "no"); + config.put("tcp.nodelay", "yes"); // 加速 + session.setConfig(config); + 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; while ((len = in.read(buf)) != -1) { out.write(buf, 0, len); @@ -90,24 +69,17 @@ public class DockerUtil { return out.toString(StandardCharsets.UTF_8).trim(); } catch (Exception e) { - // 执行失败,清理坏连接 - if (session != null) { - session.disconnect(); - sessionCache.remove(account.getAccountId()); - } return null; } finally { - try { - if (in != null) in.close(); - if (channel != null) channel.disconnect(); - out.close(); - } catch (Exception ignored) {} + try { if (in != null) in.close(); } catch (Exception ignored) {} + try { if (channel != null) channel.disconnect(); } catch (Exception ignored) {} + try { if (session != null) session.disconnect(); } catch (Exception ignored) {} } } public static List listContainers(MySftpAccounts accounts, boolean all) { - String FORMAT = "{{.ID}}|{{.Image}}|{{.Command}}|{{.CreatedAt}}|{{.Status}}|{{.Ports}}|{{.Names}}"; - String cmd = (all ? "docker ps -a" : "docker ps") + " --format \"" + FORMAT + "\""; + String fmt = "{{.ID}}|{{.Image}}|{{.Command}}|{{.CreatedAt}}|{{.Status}}|{{.Ports}}|{{.Names}}"; + String cmd = (all ? "docker ps -a" : "docker ps") + " --format \"" + fmt + "\""; String output = runCommand(accounts, cmd); if (output == null || output.isBlank()) { @@ -132,6 +104,7 @@ public class DockerUtil { .collect(Collectors.toList()); } + // ====================== 容器操作 ====================== public static DockerResult start(MySftpAccounts accounts, String containerId) { String res = runCommand(accounts, "docker start " + containerId); return res != null ? DockerResult.ok(res) : DockerResult.fail("启动失败"); @@ -162,28 +135,21 @@ public class DockerUtil { String res = runCommand(accounts, "docker inspect " + containerId); return res != null ? DockerResult.ok(res) : DockerResult.fail("查询详情失败"); } + public static SystemInfo systemInfo(MySftpAccounts accounts) { SystemInfo info = new SystemInfo(); - String output = runCommand(accounts, - "top -bn1 | grep 'Cpu(s)' | awk '{printf \"%.1f\", 100-$8}'; echo; " + - "free | grep Mem | awk '{printf \"%.1f\", $3/$2*100}'; echo; " + - "df -h / | grep / | awk '{gsub(/%/,\"\"); print $5}'" - ); + String cmd = + "top -bn1 | grep 'Cpu(s)' | awk '{printf \"%.1f\", 100-$8}'; echo ; " + + "free | grep Mem | awk '{printf \"%.1f\", $3/$2*100}'; echo ; " + + "df -h / | grep / | awk '{gsub(/%/,\"\"); print $5}'"; + String output = runCommand(accounts, cmd); if (output == null) return info; + String[] lines = output.split("\\R"); if (lines.length >= 1) info.setCpu(lines[0].trim()); if (lines.length >= 2) info.setMemory(lines[1].trim()); if (lines.length >= 3) info.setDisk(lines[2].trim()); 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(); - } } \ No newline at end of file