From b2cba06872bcb28fd582b895ac112aab53d4976a Mon Sep 17 00:00:00 2001 From: bwcx_jzy Date: Wed, 23 Feb 2022 10:31:31 +0800 Subject: [PATCH] =?UTF-8?q?feat(fix)=20=E5=9C=A8=E7=BA=BF=E5=8D=87?= =?UTF-8?q?=E7=BA=A7=E6=89=A7=E8=A1=8C=E8=84=9A=E6=9C=AC=E3=80=81=E8=84=9A?= =?UTF-8?q?=E6=9C=AC=E6=A8=A1=E7=89=88=E7=AD=89=E5=85=BC=E5=AE=B9=20debian?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + .../java/io/jpom/script/DslScriptBuilder.java | 5 +- .../io/jpom/script/ScriptProcessBuilder.java | 311 ++++--- .../main/java/io/jpom/JpomApplication.java | 4 +- .../main/java/io/jpom/util/CommandUtil.java | 361 ++++---- .../java/io/jpom/build/ReleaseManage.java | 817 +++++++++--------- .../io/jpom/socket/ScriptProcessBuilder.java | 321 ++++--- web-vue/src/pages/script/script-list.vue | 10 +- web-vue/src/pages/ssh/command.vue | 9 +- web-vue/src/pages/ssh/ssh.vue | 13 +- 10 files changed, 925 insertions(+), 927 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1383b1ce2..4a9b5cf53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ 3. 【server】在线构建 ssh 发布选择授权目录切换不生效问题(感谢@天天) 4. 【server】在线构建本地构建命令不能换行问题(感谢@华仔) 5. 【server】日志弹窗新增行号 +6. 【server】在线升级执行脚本、脚本模版等兼容 `debian` (感谢@wxyShine [Gitee issues I4UQBD](https://gitee.com/dromara/Jpom/issues/I4UQBD) ) ------ diff --git a/modules/agent/src/main/java/io/jpom/script/DslScriptBuilder.java b/modules/agent/src/main/java/io/jpom/script/DslScriptBuilder.java index 9df0bca30..0ec5ec4bc 100644 --- a/modules/agent/src/main/java/io/jpom/script/DslScriptBuilder.java +++ b/modules/agent/src/main/java/io/jpom/script/DslScriptBuilder.java @@ -29,7 +29,6 @@ import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.LineHandler; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.system.SystemUtil; import cn.jiangzeyin.common.DefaultSystemLog; import cn.jiangzeyin.common.spring.SpringUtil; import io.jpom.model.data.DslYmlDto; @@ -75,9 +74,7 @@ public class DslScriptBuilder extends BaseRunScript implements Runnable { ProcessBuilder processBuilder = new ProcessBuilder(); List command = StrUtil.splitTrim(args, StrUtil.SPACE); command.add(0, script); - if (SystemUtil.getOsInfo().isLinux() || SystemUtil.getOsInfo().isMac()) { - command.add(0, CommandUtil.SUFFIX); - } + command.add(0, CommandUtil.EXECUTE_PREFIX); DefaultSystemLog.getLog().debug(CollUtil.join(command, StrUtil.SPACE)); if (environment != null) { processBuilder.environment().putAll(environment); diff --git a/modules/agent/src/main/java/io/jpom/script/ScriptProcessBuilder.java b/modules/agent/src/main/java/io/jpom/script/ScriptProcessBuilder.java index a0ee171de..7c27a7ce6 100644 --- a/modules/agent/src/main/java/io/jpom/script/ScriptProcessBuilder.java +++ b/modules/agent/src/main/java/io/jpom/script/ScriptProcessBuilder.java @@ -30,7 +30,6 @@ import cn.hutool.core.io.LineHandler; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.system.SystemUtil; import cn.jiangzeyin.common.DefaultSystemLog; import cn.jiangzeyin.common.JsonMessage; import com.alibaba.fastjson.JSONObject; @@ -53,171 +52,169 @@ import java.util.concurrent.ConcurrentHashMap; * @date 2019/4/25 */ public class ScriptProcessBuilder extends BaseRunScript implements Runnable { - /** - * 执行中的缓存 - */ - private static final ConcurrentHashMap FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>(); + /** + * 执行中的缓存 + */ + private static final ConcurrentHashMap FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>(); - private final ProcessBuilder processBuilder; - private final Set sessions = new HashSet<>(); - private final String executeId; + private final ProcessBuilder processBuilder; + private final Set sessions = new HashSet<>(); + private final String executeId; - private ScriptProcessBuilder(NodeScriptModel nodeScriptModel, String executeId, String args) { - super(nodeScriptModel.logFile(executeId)); - this.executeId = executeId; + private ScriptProcessBuilder(NodeScriptModel nodeScriptModel, String executeId, String args) { + super(nodeScriptModel.logFile(executeId)); + this.executeId = executeId; - File scriptFile = nodeScriptModel.getFile(true); - // - String script = FileUtil.getAbsolutePath(scriptFile); - processBuilder = new ProcessBuilder(); - List command = StrUtil.splitTrim(args, StrUtil.SPACE); - command.add(0, script); - if (SystemUtil.getOsInfo().isLinux() || SystemUtil.getOsInfo().isMac()) { - command.add(0, CommandUtil.SUFFIX); - } - DefaultSystemLog.getLog().debug(CollUtil.join(command, StrUtil.SPACE)); - processBuilder.redirectErrorStream(true); - processBuilder.command(command); - processBuilder.directory(scriptFile.getParentFile()); - } + File scriptFile = nodeScriptModel.getFile(true); + // + String script = FileUtil.getAbsolutePath(scriptFile); + processBuilder = new ProcessBuilder(); + List command = StrUtil.splitTrim(args, StrUtil.SPACE); + command.add(0, script); + command.add(0, CommandUtil.EXECUTE_PREFIX); + DefaultSystemLog.getLog().debug(CollUtil.join(command, StrUtil.SPACE)); + processBuilder.redirectErrorStream(true); + processBuilder.command(command); + processBuilder.directory(scriptFile.getParentFile()); + } - /** - * 创建执行 并监听 - * - * @param nodeScriptModel 脚本模版 - * @param executeId 执行ID - * @param args 参数 - */ - public static ScriptProcessBuilder create(NodeScriptModel nodeScriptModel, String executeId, String args) { - return FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.computeIfAbsent(executeId, file1 -> { - ScriptProcessBuilder scriptProcessBuilder1 = new ScriptProcessBuilder(nodeScriptModel, executeId, args); - ThreadUtil.execute(scriptProcessBuilder1); - return scriptProcessBuilder1; - }); - } + /** + * 创建执行 并监听 + * + * @param nodeScriptModel 脚本模版 + * @param executeId 执行ID + * @param args 参数 + */ + public static ScriptProcessBuilder create(NodeScriptModel nodeScriptModel, String executeId, String args) { + return FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.computeIfAbsent(executeId, file1 -> { + ScriptProcessBuilder scriptProcessBuilder1 = new ScriptProcessBuilder(nodeScriptModel, executeId, args); + ThreadUtil.execute(scriptProcessBuilder1); + return scriptProcessBuilder1; + }); + } - /** - * 创建执行 并监听 - * - * @param nodeScriptModel 脚本模版 - * @param executeId 执行ID - * @param args 参数 - * @param session 会话 - */ - public static void addWatcher(NodeScriptModel nodeScriptModel, String executeId, String args, Session session) { - ScriptProcessBuilder scriptProcessBuilder = create(nodeScriptModel, executeId, args); - // - if (scriptProcessBuilder.sessions.add(session)) { - if (FileUtil.exist(scriptProcessBuilder.logFile)) { - // 读取之前的信息并发送 - FileUtil.readLines(scriptProcessBuilder.logFile, CharsetUtil.CHARSET_UTF_8, (LineHandler) line -> { - try { - SocketSessionUtil.send(session, line); - } catch (IOException e) { - DefaultSystemLog.getLog().error("发送消息失败", e); - } - }); - } - } - } + /** + * 创建执行 并监听 + * + * @param nodeScriptModel 脚本模版 + * @param executeId 执行ID + * @param args 参数 + * @param session 会话 + */ + public static void addWatcher(NodeScriptModel nodeScriptModel, String executeId, String args, Session session) { + ScriptProcessBuilder scriptProcessBuilder = create(nodeScriptModel, executeId, args); + // + if (scriptProcessBuilder.sessions.add(session)) { + if (FileUtil.exist(scriptProcessBuilder.logFile)) { + // 读取之前的信息并发送 + FileUtil.readLines(scriptProcessBuilder.logFile, CharsetUtil.CHARSET_UTF_8, (LineHandler) line -> { + try { + SocketSessionUtil.send(session, line); + } catch (IOException e) { + DefaultSystemLog.getLog().error("发送消息失败", e); + } + }); + } + } + } - /** - * 判断是否还在执行中 - * - * @param executeId 执行id - * @return true 还在执行 - */ - public static boolean isRun(String executeId) { - return FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.containsKey(executeId); - } + /** + * 判断是否还在执行中 + * + * @param executeId 执行id + * @return true 还在执行 + */ + public static boolean isRun(String executeId) { + return FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.containsKey(executeId); + } - /** - * 关闭会话 - * - * @param session 会话 - */ - public static void stopWatcher(Session session) { - Collection scriptProcessBuilders = FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.values(); - for (ScriptProcessBuilder scriptProcessBuilder : scriptProcessBuilders) { - Set sessions = scriptProcessBuilder.sessions; - sessions.removeIf(session1 -> session1.getId().equals(session.getId())); - } - } + /** + * 关闭会话 + * + * @param session 会话 + */ + public static void stopWatcher(Session session) { + Collection scriptProcessBuilders = FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.values(); + for (ScriptProcessBuilder scriptProcessBuilder : scriptProcessBuilders) { + Set sessions = scriptProcessBuilder.sessions; + sessions.removeIf(session1 -> session1.getId().equals(session.getId())); + } + } - /** - * 停止脚本命令 - * - * @param executeId 执行ID - */ - public static void stopRun(String executeId) { - ScriptProcessBuilder scriptProcessBuilder = FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.get(executeId); - if (scriptProcessBuilder != null) { - scriptProcessBuilder.end("停止运行"); - } - } + /** + * 停止脚本命令 + * + * @param executeId 执行ID + */ + public static void stopRun(String executeId) { + ScriptProcessBuilder scriptProcessBuilder = FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.get(executeId); + if (scriptProcessBuilder != null) { + scriptProcessBuilder.end("停止运行"); + } + } - @Override - public void run() { - //初始化ProcessBuilder对象 - try { - this.handle("start execute:" + DateUtil.now()); - process = processBuilder.start(); - { - inputStream = process.getInputStream(); - IoUtil.readLines(inputStream, ExtConfigBean.getInstance().getConsoleLogCharset(), (LineHandler) ScriptProcessBuilder.this::handle); - } - int waitFor = process.waitFor(); - JsonMessage jsonMessage = new JsonMessage<>(200, "执行完毕:" + waitFor); - JSONObject jsonObject = jsonMessage.toJson(); - jsonObject.put("op", ConsoleCommandOp.stop.name()); - this.end(jsonObject.toString()); - this.handle("execute done:" + waitFor + " time:" + DateUtil.now()); - } catch (Exception e) { - DefaultSystemLog.getLog().error("执行异常", e); - this.end("执行异常:" + e.getMessage()); - } finally { - this.close(); - } - } + @Override + public void run() { + //初始化ProcessBuilder对象 + try { + this.handle("start execute:" + DateUtil.now()); + process = processBuilder.start(); + { + inputStream = process.getInputStream(); + IoUtil.readLines(inputStream, ExtConfigBean.getInstance().getConsoleLogCharset(), (LineHandler) ScriptProcessBuilder.this::handle); + } + int waitFor = process.waitFor(); + JsonMessage jsonMessage = new JsonMessage<>(200, "执行完毕:" + waitFor); + JSONObject jsonObject = jsonMessage.toJson(); + jsonObject.put("op", ConsoleCommandOp.stop.name()); + this.end(jsonObject.toString()); + this.handle("execute done:" + waitFor + " time:" + DateUtil.now()); + } catch (Exception e) { + DefaultSystemLog.getLog().error("执行异常", e); + this.end("执行异常:" + e.getMessage()); + } finally { + this.close(); + } + } - /** - * 结束执行 - * - * @param msg 响应的消息 - */ - @Override - protected void end(String msg) { - Iterator iterator = sessions.iterator(); - while (iterator.hasNext()) { - Session session = iterator.next(); - try { - SocketSessionUtil.send(session, msg); - } catch (IOException e) { - DefaultSystemLog.getLog().error("发送消息失败", e); - } - iterator.remove(); - } - FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.remove(this.executeId); - } + /** + * 结束执行 + * + * @param msg 响应的消息 + */ + @Override + protected void end(String msg) { + Iterator iterator = sessions.iterator(); + while (iterator.hasNext()) { + Session session = iterator.next(); + try { + SocketSessionUtil.send(session, msg); + } catch (IOException e) { + DefaultSystemLog.getLog().error("发送消息失败", e); + } + iterator.remove(); + } + FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.remove(this.executeId); + } - /** - * 响应 - * - * @param line 信息 - */ - @Override - protected void handle(String line) { - super.handle(line); - // - Iterator iterator = sessions.iterator(); - while (iterator.hasNext()) { - Session session = iterator.next(); - try { - SocketSessionUtil.send(session, line); - } catch (IOException e) { - DefaultSystemLog.getLog().error("发送消息失败", e); - iterator.remove(); - } - } - } + /** + * 响应 + * + * @param line 信息 + */ + @Override + protected void handle(String line) { + super.handle(line); + // + Iterator iterator = sessions.iterator(); + while (iterator.hasNext()) { + Session session = iterator.next(); + try { + SocketSessionUtil.send(session, line); + } catch (IOException e) { + DefaultSystemLog.getLog().error("发送消息失败", e); + iterator.remove(); + } + } + } } diff --git a/modules/common/src/main/java/io/jpom/JpomApplication.java b/modules/common/src/main/java/io/jpom/JpomApplication.java index 114112926..fa869fd41 100644 --- a/modules/common/src/main/java/io/jpom/JpomApplication.java +++ b/modules/common/src/main/java/io/jpom/JpomApplication.java @@ -196,9 +196,7 @@ public class JpomApplication extends ApplicationBuilder { // Waiting for method caller,For example, the interface response ThreadUtil.sleep(2, TimeUnit.SECONDS); try { - String command = SystemUtil.getOsInfo().isWindows() ? StrUtil.EMPTY : CommandUtil.SUFFIX; - - command += " " + FileUtil.getAbsolutePath(scriptFile) + " restart upgrade"; + String command = CommandUtil.EXECUTE_PREFIX + StrUtil.SPACE + FileUtil.getAbsolutePath(scriptFile) + " restart upgrade"; if (SystemUtil.getOsInfo().isWindows()) { CommandUtil.execSystemCommand(command, scriptFile.getParentFile()); } else { diff --git a/modules/common/src/main/java/io/jpom/util/CommandUtil.java b/modules/common/src/main/java/io/jpom/util/CommandUtil.java index 4ba191b6d..1e62fde04 100644 --- a/modules/common/src/main/java/io/jpom/util/CommandUtil.java +++ b/modules/common/src/main/java/io/jpom/util/CommandUtil.java @@ -23,7 +23,10 @@ package io.jpom.util; import cn.hutool.core.io.FileUtil; -import cn.hutool.core.util.*; +import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.RuntimeUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.system.SystemUtil; import cn.jiangzeyin.common.DefaultSystemLog; import io.jpom.system.ExtConfigBean; @@ -42,189 +45,193 @@ import java.util.List; * @date 2019/4/15 */ public class CommandUtil { - /** - * 系统命令 - */ - private static final List COMMAND = new ArrayList<>(); - /** - * 文件后缀 - */ - public static final String SUFFIX; + /** + * 系统命令 + */ + private static final List COMMAND = new ArrayList<>(); + /** + * 文件后缀 + */ + public static final String SUFFIX; + /** + * 执行前缀 + */ + public static final String EXECUTE_PREFIX; - static { - if (SystemUtil.getOsInfo().isLinux()) { - //执行linux系统命令 - COMMAND.add("/bin/bash"); - COMMAND.add("-c"); - } else if (SystemUtil.getOsInfo().isMac()) { - COMMAND.add("/bin/bash"); - COMMAND.add("-c"); - } else { - COMMAND.add("cmd"); - COMMAND.add("/c"); - } - /** - * 文件后缀 - */ - if (SystemUtil.getOsInfo().isWindows()) { - SUFFIX = "bat"; - } else { - SUFFIX = "sh"; - } - } + static { + if (SystemUtil.getOsInfo().isLinux()) { + //执行linux系统命令 + COMMAND.add("/bin/bash"); + COMMAND.add("-c"); + } else if (SystemUtil.getOsInfo().isMac()) { + COMMAND.add("/bin/bash"); + COMMAND.add("-c"); + } else { + COMMAND.add("cmd"); + COMMAND.add("/c"); + } + // + if (SystemUtil.getOsInfo().isWindows()) { + SUFFIX = "bat"; + EXECUTE_PREFIX = StrUtil.EMPTY; + } else { + SUFFIX = "sh"; + EXECUTE_PREFIX = "bash"; + } + } - /** - * 获取执行命令的 前缀 - * - * @return list - */ - public static List getCommand() { - return ObjectUtil.clone(COMMAND); - } + /** + * 获取执行命令的 前缀 + * + * @return list + */ + public static List getCommand() { + return ObjectUtil.clone(COMMAND); + } - public static String execSystemCommand(String command) { - return execSystemCommand(command, null); - } + public static String execSystemCommand(String command) { + return execSystemCommand(command, null); + } - /** - * 在指定文件夹下执行命令 - * - * @param command 命令 - * @param file 文件夹 - * @return msg - */ - public static String execSystemCommand(String command, File file) { - String newCommand = StrUtil.replace(command, StrUtil.CRLF, StrUtil.SPACE); - newCommand = StrUtil.replace(newCommand, StrUtil.LF, StrUtil.SPACE); - String result = "error"; - try { - List commands = getCommand(); - commands.add(newCommand); - String[] cmd = commands.toArray(new String[]{}); - result = exec(cmd, file); - } catch (Exception e) { - DefaultSystemLog.getLog().error("执行命令异常", e); - result += e.getMessage(); - } - return result; - } + /** + * 在指定文件夹下执行命令 + * + * @param command 命令 + * @param file 文件夹 + * @return msg + */ + public static String execSystemCommand(String command, File file) { + String newCommand = StrUtil.replace(command, StrUtil.CRLF, StrUtil.SPACE); + newCommand = StrUtil.replace(newCommand, StrUtil.LF, StrUtil.SPACE); + String result = "error"; + try { + List commands = getCommand(); + commands.add(newCommand); + String[] cmd = commands.toArray(new String[]{}); + result = exec(cmd, file); + } catch (Exception e) { + DefaultSystemLog.getLog().error("执行命令异常", e); + result += e.getMessage(); + } + return result; + } - /** - * 执行命令 - * - * @param cmd 命令行 - * @return 结果 - * @throws IOException IO - */ - private static String exec(String[] cmd, File file) throws IOException { - Process process = new ProcessBuilder(cmd).directory(file).redirectErrorStream(true).start(); - Charset charset; - boolean log; - try { - charset = ExtConfigBean.getInstance().getConsoleLogCharset(); - log = true; - } catch (Exception e) { - // 直接执行,使用默认编码格式 - charset = CharsetUtil.systemCharset(); - // 不记录日志 - log = false; - } - charset = ObjectUtil.defaultIfNull(charset, CharsetUtil.defaultCharset()); - String result = RuntimeUtil.getResult(process, charset); - if (log) { - DefaultSystemLog.getLog().debug("exec {} {} {}", charset.name(), Arrays.toString(cmd), result); - } - return result; - } + /** + * 执行命令 + * + * @param cmd 命令行 + * @return 结果 + * @throws IOException IO + */ + private static String exec(String[] cmd, File file) throws IOException { + Process process = new ProcessBuilder(cmd).directory(file).redirectErrorStream(true).start(); + Charset charset; + boolean log; + try { + charset = ExtConfigBean.getInstance().getConsoleLogCharset(); + log = true; + } catch (Exception e) { + // 直接执行,使用默认编码格式 + charset = CharsetUtil.systemCharset(); + // 不记录日志 + log = false; + } + charset = ObjectUtil.defaultIfNull(charset, CharsetUtil.defaultCharset()); + String result = RuntimeUtil.getResult(process, charset); + if (log) { + DefaultSystemLog.getLog().debug("exec {} {} {}", charset.name(), Arrays.toString(cmd), result); + } + return result; + } - /** - * 异步执行命令 - * - * @param file 文件夹 - * @param command 命令 - * @throws IOException 异常 - */ - public static void asyncExeLocalCommand(File file, String command) throws Exception { - String newCommand = StrUtil.replace(command, StrUtil.CRLF, StrUtil.SPACE); - newCommand = StrUtil.replace(newCommand, StrUtil.LF, StrUtil.SPACE); - // - DefaultSystemLog.getLog().debug(newCommand); - List commands = getCommand(); - commands.add(newCommand); - ProcessBuilder pb = new ProcessBuilder(commands); - if (file != null) { - pb.directory(file); - } - pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); - pb.redirectError(ProcessBuilder.Redirect.INHERIT); - pb.redirectInput(ProcessBuilder.Redirect.INHERIT); - pb.start(); - } + /** + * 异步执行命令 + * + * @param file 文件夹 + * @param command 命令 + * @throws IOException 异常 + */ + public static void asyncExeLocalCommand(File file, String command) throws Exception { + String newCommand = StrUtil.replace(command, StrUtil.CRLF, StrUtil.SPACE); + newCommand = StrUtil.replace(newCommand, StrUtil.LF, StrUtil.SPACE); + // + DefaultSystemLog.getLog().debug(newCommand); + List commands = getCommand(); + commands.add(newCommand); + ProcessBuilder pb = new ProcessBuilder(commands); + if (file != null) { + pb.directory(file); + } + pb.redirectOutput(ProcessBuilder.Redirect.INHERIT); + pb.redirectError(ProcessBuilder.Redirect.INHERIT); + pb.redirectInput(ProcessBuilder.Redirect.INHERIT); + pb.start(); + } - /** - * 判断是否包含删除命令 - * - * @param script 命令行 - * @return true 包含 - */ - public static boolean checkContainsDel(String script) { - // 判断删除 - String[] commands = StrUtil.splitToArray(script, StrUtil.LF); - for (String commandItem : commands) { - if (checkContainsDelItem(commandItem)) { - return true; - } - } - return false; - } + /** + * 判断是否包含删除命令 + * + * @param script 命令行 + * @return true 包含 + */ + public static boolean checkContainsDel(String script) { + // 判断删除 + String[] commands = StrUtil.splitToArray(script, StrUtil.LF); + for (String commandItem : commands) { + if (checkContainsDelItem(commandItem)) { + return true; + } + } + return false; + } - /** - * 执行系统命令 快速删除. - * 执行删除后再检查文件是否存在 - * - * @param file 文件或者文件夹 - * @return true 文件还存在 - */ - public static boolean systemFastDel(File file) { - String path = FileUtil.getAbsolutePath(file); - String command; - if (SystemUtil.getOsInfo().isWindows()) { - // Windows - command = StrUtil.format("rd /s/q \"{}\"", path); - } else { - // Linux MacOS - command = StrUtil.format("rm -rf '{}'", path); - } - CommandUtil.execSystemCommand(command); - // 再次尝试 - boolean del = FileUtil.del(file); - if (!del) { - FileUtil.del(file.toPath()); - } - return FileUtil.exist(file); - } + /** + * 执行系统命令 快速删除. + * 执行删除后再检查文件是否存在 + * + * @param file 文件或者文件夹 + * @return true 文件还存在 + */ + public static boolean systemFastDel(File file) { + String path = FileUtil.getAbsolutePath(file); + String command; + if (SystemUtil.getOsInfo().isWindows()) { + // Windows + command = StrUtil.format("rd /s/q \"{}\"", path); + } else { + // Linux MacOS + command = StrUtil.format("rm -rf '{}'", path); + } + CommandUtil.execSystemCommand(command); + // 再次尝试 + boolean del = FileUtil.del(file); + if (!del) { + FileUtil.del(file.toPath()); + } + return FileUtil.exist(file); + } - private static boolean checkContainsDelItem(String script) { - String[] split = StrUtil.splitToArray(script, StrUtil.SPACE); - if (SystemUtil.getOsInfo().isWindows()) { - for (String s : split) { - if (StrUtil.startWithAny(s, "rd", "del")) { - return true; - } - if (StrUtil.containsAnyIgnoreCase(s, " rd", " del")) { - return true; - } - } - } else { - for (String s : split) { - if (StrUtil.startWithAny(s, "rm", "\\rm")) { - return true; - } - if (StrUtil.containsAnyIgnoreCase(s, " rm", " \\rm", "&rm", "&\\rm")) { - return true; - } - } - } - return false; - } + private static boolean checkContainsDelItem(String script) { + String[] split = StrUtil.splitToArray(script, StrUtil.SPACE); + if (SystemUtil.getOsInfo().isWindows()) { + for (String s : split) { + if (StrUtil.startWithAny(s, "rd", "del")) { + return true; + } + if (StrUtil.containsAnyIgnoreCase(s, " rd", " del")) { + return true; + } + } + } else { + for (String s : split) { + if (StrUtil.startWithAny(s, "rm", "\\rm")) { + return true; + } + if (StrUtil.containsAnyIgnoreCase(s, " rm", " \\rm", "&rm", "&\\rm")) { + return true; + } + } + } + return false; + } } diff --git a/modules/server/src/main/java/io/jpom/build/ReleaseManage.java b/modules/server/src/main/java/io/jpom/build/ReleaseManage.java index 4b9f6ec36..5a020ec55 100644 --- a/modules/server/src/main/java/io/jpom/build/ReleaseManage.java +++ b/modules/server/src/main/java/io/jpom/build/ReleaseManage.java @@ -37,7 +37,6 @@ import cn.hutool.crypto.SecureUtil; import cn.hutool.extra.ssh.JschUtil; import cn.hutool.extra.ssh.Sftp; import cn.hutool.http.HttpStatus; -import cn.hutool.system.SystemUtil; import cn.jiangzeyin.common.JsonMessage; import cn.jiangzeyin.common.spring.SpringUtil; import com.alibaba.fastjson.JSONArray; @@ -86,22 +85,22 @@ import java.util.stream.Collectors; @Builder public class ReleaseManage implements Runnable { - private final UserModel userModel; - private final int buildId; - private final BuildExtraModule buildExtraModule; - private final String logId; - private final BuildExecuteService buildExecuteService; + private final UserModel userModel; + private final int buildId; + private final BuildExtraModule buildExtraModule; + private final String logId; + private final BuildExecuteService buildExecuteService; - private LogRecorder logRecorder; - private File resultFile; + private LogRecorder logRecorder; + private File resultFile; - private void init() { - if (this.logRecorder == null) { - File logFile = BuildUtil.getLogFile(buildExtraModule.getId(), buildId); - this.logRecorder = LogRecorder.builder().file(logFile).build(); - } - this.resultFile = BuildUtil.getHistoryPackageFile(buildExtraModule.getId(), this.buildId, buildExtraModule.getResultDirFile()); - } + private void init() { + if (this.logRecorder == null) { + File logFile = BuildUtil.getLogFile(buildExtraModule.getId(), buildId); + this.logRecorder = LogRecorder.builder().file(logFile).build(); + } + this.resultFile = BuildUtil.getHistoryPackageFile(buildExtraModule.getId(), this.buildId, buildExtraModule.getResultDirFile()); + } // /** // * new ReleaseManage constructor @@ -138,417 +137,417 @@ public class ReleaseManage implements Runnable { // } - public void updateStatus(BuildStatus status) { - buildExecuteService.updateStatus(this.buildExtraModule.getId(), this.logId, status); - } + public void updateStatus(BuildStatus status) { + buildExecuteService.updateStatus(this.buildExtraModule.getId(), this.logId, status); + } - /** - * 不修改为发布中状态 - */ - public void start() { - init(); - updateStatus(BuildStatus.PubIng); - logRecorder.info("start release:" + FileUtil.readableFileSize(FileUtil.size(this.resultFile))); - if (!this.resultFile.exists()) { - logRecorder.info("不存在构建产物"); - updateStatus(BuildStatus.PubError); - return; - } - long time = SystemClock.now(); - int releaseMethod = this.buildExtraModule.getReleaseMethod(); - logRecorder.info("release method:" + BaseEnum.getDescByCode(BuildReleaseMethod.class, releaseMethod)); - try { - if (releaseMethod == BuildReleaseMethod.Outgiving.getCode()) { - // - this.doOutGiving(); - } else if (releaseMethod == BuildReleaseMethod.Project.getCode()) { - this.doProject(); - } else if (releaseMethod == BuildReleaseMethod.Ssh.getCode()) { - this.doSsh(); - } else if (releaseMethod == BuildReleaseMethod.LocalCommand.getCode()) { - this.localCommand(); - } else if (releaseMethod == BuildReleaseMethod.DockerImage.getCode()) { - this.doDockerImage(); - } else { - logRecorder.info(" 没有实现的发布分发:" + releaseMethod); - } - } catch (Exception e) { - this.pubLog("发布异常", e); - return; - } - logRecorder.info("release complete : " + DateUtil.formatBetween(SystemClock.now() - time, BetweenFormatter.Level.MILLISECOND)); - updateStatus(BuildStatus.PubSuccess); - } + /** + * 不修改为发布中状态 + */ + public void start() { + init(); + updateStatus(BuildStatus.PubIng); + logRecorder.info("start release:" + FileUtil.readableFileSize(FileUtil.size(this.resultFile))); + if (!this.resultFile.exists()) { + logRecorder.info("不存在构建产物"); + updateStatus(BuildStatus.PubError); + return; + } + long time = SystemClock.now(); + int releaseMethod = this.buildExtraModule.getReleaseMethod(); + logRecorder.info("release method:" + BaseEnum.getDescByCode(BuildReleaseMethod.class, releaseMethod)); + try { + if (releaseMethod == BuildReleaseMethod.Outgiving.getCode()) { + // + this.doOutGiving(); + } else if (releaseMethod == BuildReleaseMethod.Project.getCode()) { + this.doProject(); + } else if (releaseMethod == BuildReleaseMethod.Ssh.getCode()) { + this.doSsh(); + } else if (releaseMethod == BuildReleaseMethod.LocalCommand.getCode()) { + this.localCommand(); + } else if (releaseMethod == BuildReleaseMethod.DockerImage.getCode()) { + this.doDockerImage(); + } else { + logRecorder.info(" 没有实现的发布分发:" + releaseMethod); + } + } catch (Exception e) { + this.pubLog("发布异常", e); + return; + } + logRecorder.info("release complete : " + DateUtil.formatBetween(SystemClock.now() - time, BetweenFormatter.Level.MILLISECOND)); + updateStatus(BuildStatus.PubSuccess); + } - /** - * 格式化命令模版 - * - * @param commands 命令 - */ - private void formatCommand(String[] commands) { - for (int i = 0; i < commands.length; i++) { - commands[i] = this.formatCommandItem(commands[i]); - } - // - WorkspaceEnvVarService workspaceEnvVarService = SpringUtil.getBean(WorkspaceEnvVarService.class); - workspaceEnvVarService.formatCommand(this.buildExtraModule.getWorkspaceId(), commands); + /** + * 格式化命令模版 + * + * @param commands 命令 + */ + private void formatCommand(String[] commands) { + for (int i = 0; i < commands.length; i++) { + commands[i] = this.formatCommandItem(commands[i]); + } + // + WorkspaceEnvVarService workspaceEnvVarService = SpringUtil.getBean(WorkspaceEnvVarService.class); + workspaceEnvVarService.formatCommand(this.buildExtraModule.getWorkspaceId(), commands); - } + } - /** - * 格式化命令模版 - * - * @param command 命令 - * @return 格式化后 - */ - private String formatCommandItem(String command) { - String replace = StrUtil.replace(command, "#{BUILD_ID}", this.buildExtraModule.getId()); - replace = StrUtil.replace(replace, "#{BUILD_NAME}", this.buildExtraModule.getName()); - replace = StrUtil.replace(replace, "#{BUILD_RESULT_FILE}", FileUtil.getAbsolutePath(this.resultFile)); - replace = StrUtil.replace(replace, "#{BUILD_NUMBER_ID}", this.buildId + StrUtil.EMPTY); - return replace; - } + /** + * 格式化命令模版 + * + * @param command 命令 + * @return 格式化后 + */ + private String formatCommandItem(String command) { + String replace = StrUtil.replace(command, "#{BUILD_ID}", this.buildExtraModule.getId()); + replace = StrUtil.replace(replace, "#{BUILD_NAME}", this.buildExtraModule.getName()); + replace = StrUtil.replace(replace, "#{BUILD_RESULT_FILE}", FileUtil.getAbsolutePath(this.resultFile)); + replace = StrUtil.replace(replace, "#{BUILD_NUMBER_ID}", this.buildId + StrUtil.EMPTY); + return replace; + } - private String parseDockerTag(File envFile, String tag) { - if (!FileUtil.isFile(envFile)) { - return tag; - } - final String[] newTag = {tag}; - FileUtil.readLines(envFile, StandardCharsets.UTF_8, (LineHandler) line -> { - line = StrUtil.trim(line); - if (StrUtil.startWith(line, "#")) { - return; - } - List list = StrUtil.splitTrim(line, "="); - if (CollUtil.size(list) != 2) { - return; - } - newTag[0] = StrUtil.replace(newTag[0], "${" + list.get(0) + "}", list.get(1)); - }); - return newTag[0]; - } + private String parseDockerTag(File envFile, String tag) { + if (!FileUtil.isFile(envFile)) { + return tag; + } + final String[] newTag = {tag}; + FileUtil.readLines(envFile, StandardCharsets.UTF_8, (LineHandler) line -> { + line = StrUtil.trim(line); + if (StrUtil.startWith(line, "#")) { + return; + } + List list = StrUtil.splitTrim(line, "="); + if (CollUtil.size(list) != 2) { + return; + } + newTag[0] = StrUtil.replace(newTag[0], "${" + list.get(0) + "}", list.get(1)); + }); + return newTag[0]; + } - private void doDockerImage() { - // 生成临时目录 - File tempPath = FileUtil.file(ConfigBean.getInstance().getTempPath(), "build_temp", "docker_image", this.buildExtraModule.getId() + StrUtil.DASHED + this.buildId); - try { - File sourceFile = BuildUtil.getSourceById(this.buildExtraModule.getId()); - FileUtil.copyContent(sourceFile, tempPath, true); - File historyPackageFile = BuildUtil.getHistoryPackageFile(buildExtraModule.getId(), this.buildId, StrUtil.SLASH); - FileUtil.copyContent(historyPackageFile, tempPath, true); - // env file - File envFile = FileUtil.file(tempPath, ".env"); - String dockerTag = this.buildExtraModule.getDockerTag(); - dockerTag = this.parseDockerTag(envFile, dockerTag); - // docker file - String moduleDockerfile = this.buildExtraModule.getDockerfile(); - List list = StrUtil.splitTrim(moduleDockerfile, StrUtil.COLON); - String dockerFile = CollUtil.getLast(list); - File dockerfile = FileUtil.file(tempPath, dockerFile); - if (!FileUtil.isFile(dockerfile)) { - logRecorder.info("仓库目录下没有找到 Dockerfile 文件:", dockerFile); - return; - } - File baseDir = FileUtil.file(tempPath, list.size() == 1 ? StrUtil.SLASH : CollUtil.get(list, 0)); - // - String fromTag = this.buildExtraModule.getFromTag(); - // 根据 tag 查询 - List dockerInfoModels = buildExecuteService - .dockerInfoService - .queryByTag(this.buildExtraModule.getWorkspaceId(), 1, fromTag); - DockerInfoModel dockerInfoModel = CollUtil.getFirst(dockerInfoModels); - if (dockerInfoModel == null) { - logRecorder.info("没有可用的 docker server"); - return; - } - for (DockerInfoModel infoModel : dockerInfoModels) { - this.doDockerImage(infoModel, dockerfile, baseDir, dockerTag); - } - // 发布 docker 服务 - this.updateSwarmService(dockerTag, this.buildExtraModule.getDockerSwarmId(), this.buildExtraModule.getDockerSwarmServiceName()); - } finally { - CommandUtil.systemFastDel(tempPath); - } - } + private void doDockerImage() { + // 生成临时目录 + File tempPath = FileUtil.file(ConfigBean.getInstance().getTempPath(), "build_temp", "docker_image", this.buildExtraModule.getId() + StrUtil.DASHED + this.buildId); + try { + File sourceFile = BuildUtil.getSourceById(this.buildExtraModule.getId()); + FileUtil.copyContent(sourceFile, tempPath, true); + File historyPackageFile = BuildUtil.getHistoryPackageFile(buildExtraModule.getId(), this.buildId, StrUtil.SLASH); + FileUtil.copyContent(historyPackageFile, tempPath, true); + // env file + File envFile = FileUtil.file(tempPath, ".env"); + String dockerTag = this.buildExtraModule.getDockerTag(); + dockerTag = this.parseDockerTag(envFile, dockerTag); + // docker file + String moduleDockerfile = this.buildExtraModule.getDockerfile(); + List list = StrUtil.splitTrim(moduleDockerfile, StrUtil.COLON); + String dockerFile = CollUtil.getLast(list); + File dockerfile = FileUtil.file(tempPath, dockerFile); + if (!FileUtil.isFile(dockerfile)) { + logRecorder.info("仓库目录下没有找到 Dockerfile 文件:", dockerFile); + return; + } + File baseDir = FileUtil.file(tempPath, list.size() == 1 ? StrUtil.SLASH : CollUtil.get(list, 0)); + // + String fromTag = this.buildExtraModule.getFromTag(); + // 根据 tag 查询 + List dockerInfoModels = buildExecuteService + .dockerInfoService + .queryByTag(this.buildExtraModule.getWorkspaceId(), 1, fromTag); + DockerInfoModel dockerInfoModel = CollUtil.getFirst(dockerInfoModels); + if (dockerInfoModel == null) { + logRecorder.info("没有可用的 docker server"); + return; + } + for (DockerInfoModel infoModel : dockerInfoModels) { + this.doDockerImage(infoModel, dockerfile, baseDir, dockerTag); + } + // 发布 docker 服务 + this.updateSwarmService(dockerTag, this.buildExtraModule.getDockerSwarmId(), this.buildExtraModule.getDockerSwarmServiceName()); + } finally { + CommandUtil.systemFastDel(tempPath); + } + } - private void updateSwarmService(String dockerTag, String swarmId, String serviceName) { - if (StrUtil.isEmpty(swarmId)) { - return; - } - List splitTrim = StrUtil.splitTrim(dockerTag, StrUtil.COMMA); - String first = CollUtil.getFirst(splitTrim); - logRecorder.info("start update swarm service: {} use image {}", serviceName, first); - Map pluginMap = buildExecuteService.dockerInfoService.getBySwarmPluginMap(swarmId); - pluginMap.put("serviceId", serviceName); - pluginMap.put("image", first); - try { - IPlugin plugin = PluginFactory.getPlugin(DockerSwarmInfoService.DOCKER_PLUGIN_NAME); - plugin.execute("updateServiceImage", pluginMap); - } catch (Exception e) { - logRecorder.error("调用容器异常", e); - } - } + private void updateSwarmService(String dockerTag, String swarmId, String serviceName) { + if (StrUtil.isEmpty(swarmId)) { + return; + } + List splitTrim = StrUtil.splitTrim(dockerTag, StrUtil.COMMA); + String first = CollUtil.getFirst(splitTrim); + logRecorder.info("start update swarm service: {} use image {}", serviceName, first); + Map pluginMap = buildExecuteService.dockerInfoService.getBySwarmPluginMap(swarmId); + pluginMap.put("serviceId", serviceName); + pluginMap.put("image", first); + try { + IPlugin plugin = PluginFactory.getPlugin(DockerSwarmInfoService.DOCKER_PLUGIN_NAME); + plugin.execute("updateServiceImage", pluginMap); + } catch (Exception e) { + logRecorder.error("调用容器异常", e); + } + } - private void doDockerImage(DockerInfoModel dockerInfoModel, File dockerfile, File baseDir, String dockerTag) { - logRecorder.info("{} start build image {}", dockerInfoModel.getName(), dockerTag); - Map map = dockerInfoModel.toParameter(); - map.put("Dockerfile", dockerfile); - map.put("baseDirectory", baseDir); - // - map.put("tags", dockerTag); - Consumer logConsumer = s -> logRecorder.append(s); - map.put("logConsumer", logConsumer); - IPlugin plugin = PluginFactory.getPlugin(DockerInfoService.DOCKER_PLUGIN_NAME); - try { - plugin.execute("buildImage", map); - } catch (Exception e) { - logRecorder.error("调用容器异常", e); - } - } + private void doDockerImage(DockerInfoModel dockerInfoModel, File dockerfile, File baseDir, String dockerTag) { + logRecorder.info("{} start build image {}", dockerInfoModel.getName(), dockerTag); + Map map = dockerInfoModel.toParameter(); + map.put("Dockerfile", dockerfile); + map.put("baseDirectory", baseDir); + // + map.put("tags", dockerTag); + Consumer logConsumer = s -> logRecorder.append(s); + map.put("logConsumer", logConsumer); + IPlugin plugin = PluginFactory.getPlugin(DockerInfoService.DOCKER_PLUGIN_NAME); + try { + plugin.execute("buildImage", map); + } catch (Exception e) { + logRecorder.error("调用容器异常", e); + } + } - /** - * 本地命令执行 - */ - private void localCommand() { - // 执行命令 - String[] commands = StrUtil.splitToArray(this.buildExtraModule.getReleaseCommand(), StrUtil.LF); - if (ArrayUtil.isEmpty(commands)) { - logRecorder.info("没有需要执行的ssh命令"); - return; - } - String command = StrUtil.EMPTY; - logRecorder.info(DateUtil.now() + " start exec"); - InputStream templateInputStream = null; - try { - templateInputStream = ResourceUtil.getStream("classpath:/bin/execTemplate." + CommandUtil.SUFFIX); - if (templateInputStream == null) { - logRecorder.info("系统中没有命令模版"); - return; - } - String sshExecTemplate = IoUtil.readUtf8(templateInputStream); - StringBuilder stringBuilder = new StringBuilder(sshExecTemplate); - // 替换变量 - this.formatCommand(commands); - // - stringBuilder.append(ArrayUtil.join(commands, StrUtil.LF)); - File tempPath = ConfigBean.getInstance().getTempPath(); - File commandFile = FileUtil.file(tempPath, "build", this.buildExtraModule.getId() + StrUtil.DOT + CommandUtil.SUFFIX); - FileUtil.writeUtf8String(stringBuilder.toString(), commandFile); - // - command = SystemUtil.getOsInfo().isWindows() ? StrUtil.EMPTY : CommandUtil.SUFFIX; - command += " " + FileUtil.getAbsolutePath(commandFile); - String result = CommandUtil.execSystemCommand(command); - logRecorder.info(result); - } catch (Exception e) { - this.pubLog("执行本地命令异常:" + command, e); - } finally { - IoUtil.close(templateInputStream); - } - } + /** + * 本地命令执行 + */ + private void localCommand() { + // 执行命令 + String[] commands = StrUtil.splitToArray(this.buildExtraModule.getReleaseCommand(), StrUtil.LF); + if (ArrayUtil.isEmpty(commands)) { + logRecorder.info("没有需要执行的ssh命令"); + return; + } + String command = StrUtil.EMPTY; + logRecorder.info(DateUtil.now() + " start exec"); + InputStream templateInputStream = null; + try { + templateInputStream = ResourceUtil.getStream("classpath:/bin/execTemplate." + CommandUtil.SUFFIX); + if (templateInputStream == null) { + logRecorder.info("系统中没有命令模版"); + return; + } + String sshExecTemplate = IoUtil.readUtf8(templateInputStream); + StringBuilder stringBuilder = new StringBuilder(sshExecTemplate); + // 替换变量 + this.formatCommand(commands); + // + stringBuilder.append(ArrayUtil.join(commands, StrUtil.LF)); + File tempPath = ConfigBean.getInstance().getTempPath(); + File commandFile = FileUtil.file(tempPath, "build", this.buildExtraModule.getId() + StrUtil.DOT + CommandUtil.SUFFIX); + FileUtil.writeUtf8String(stringBuilder.toString(), commandFile); + // + // command = SystemUtil.getOsInfo().isWindows() ? StrUtil.EMPTY : CommandUtil.SUFFIX; + command = CommandUtil.EXECUTE_PREFIX + StrUtil.SPACE + FileUtil.getAbsolutePath(commandFile); + String result = CommandUtil.execSystemCommand(command); + logRecorder.info(result); + } catch (Exception e) { + this.pubLog("执行本地命令异常:" + command, e); + } finally { + IoUtil.close(templateInputStream); + } + } - /** - * ssh 发布 - */ - private void doSsh() { - String releaseMethodDataId = this.buildExtraModule.getReleaseMethodDataId(); - SshService sshService = SpringUtil.getBean(SshService.class); - List strings = StrUtil.splitTrim(releaseMethodDataId, StrUtil.COMMA); - for (String releaseMethodDataIdItem : strings) { - SshModel item = sshService.getByKey(releaseMethodDataIdItem, false); - if (item == null) { - logRecorder.info("没有找到对应的ssh项:" + releaseMethodDataIdItem); - continue; - } - this.doSsh(item, sshService); - } - } + /** + * ssh 发布 + */ + private void doSsh() { + String releaseMethodDataId = this.buildExtraModule.getReleaseMethodDataId(); + SshService sshService = SpringUtil.getBean(SshService.class); + List strings = StrUtil.splitTrim(releaseMethodDataId, StrUtil.COMMA); + for (String releaseMethodDataIdItem : strings) { + SshModel item = sshService.getByKey(releaseMethodDataIdItem, false); + if (item == null) { + logRecorder.info("没有找到对应的ssh项:" + releaseMethodDataIdItem); + continue; + } + this.doSsh(item, sshService); + } + } - private void doSsh(SshModel item, SshService sshService) { - Session session = SshService.getSessionByModel(item); - try { - String releasePath = this.buildExtraModule.getReleasePath(); - if (StrUtil.isEmpty(releasePath)) { - logRecorder.info("发布目录为空"); - } else { - logRecorder.info("{} {} start ftp upload", DateUtil.now(), item.getName()); - try (Sftp sftp = new Sftp(session, item.getCharsetT())) { - String prefix = ""; - if (!StrUtil.startWith(releasePath, StrUtil.SLASH)) { - prefix = sftp.pwd(); - } - String normalizePath = FileUtil.normalize(prefix + StrUtil.SLASH + releasePath); - if (this.buildExtraModule.isClearOld()) { - try { - sftp.delDir(normalizePath); - } catch (Exception e) { - if (!StrUtil.startWithIgnoreCase(e.getMessage(), "No such file")) { - this.pubLog("清除构建产物失败", e); - } - } - } - sftp.syncUpload(this.resultFile, normalizePath); - logRecorder.info("{} ftp upload done", item.getName()); - } catch (Exception e) { - this.pubLog("执行ssh发布异常", e); - } - } - } finally { - JschUtil.close(session); - } - logRecorder.info(""); - // 执行命令 - String[] commands = StrUtil.splitToArray(this.buildExtraModule.getReleaseCommand(), StrUtil.LF); - if (commands == null || commands.length <= 0) { - logRecorder.info("没有需要执行的ssh命令"); - return; - } - // 替换变量 - this.formatCommand(commands); - // - logRecorder.info("{} {} start exec", DateUtil.now(), item.getName()); - try { - String s = sshService.exec(item, commands); - logRecorder.info(s); - } catch (Exception e) { - this.pubLog(item.getName() + " 执行异常", e); - } - } + private void doSsh(SshModel item, SshService sshService) { + Session session = SshService.getSessionByModel(item); + try { + String releasePath = this.buildExtraModule.getReleasePath(); + if (StrUtil.isEmpty(releasePath)) { + logRecorder.info("发布目录为空"); + } else { + logRecorder.info("{} {} start ftp upload", DateUtil.now(), item.getName()); + try (Sftp sftp = new Sftp(session, item.getCharsetT())) { + String prefix = ""; + if (!StrUtil.startWith(releasePath, StrUtil.SLASH)) { + prefix = sftp.pwd(); + } + String normalizePath = FileUtil.normalize(prefix + StrUtil.SLASH + releasePath); + if (this.buildExtraModule.isClearOld()) { + try { + sftp.delDir(normalizePath); + } catch (Exception e) { + if (!StrUtil.startWithIgnoreCase(e.getMessage(), "No such file")) { + this.pubLog("清除构建产物失败", e); + } + } + } + sftp.syncUpload(this.resultFile, normalizePath); + logRecorder.info("{} ftp upload done", item.getName()); + } catch (Exception e) { + this.pubLog("执行ssh发布异常", e); + } + } + } finally { + JschUtil.close(session); + } + logRecorder.info(""); + // 执行命令 + String[] commands = StrUtil.splitToArray(this.buildExtraModule.getReleaseCommand(), StrUtil.LF); + if (commands == null || commands.length <= 0) { + logRecorder.info("没有需要执行的ssh命令"); + return; + } + // 替换变量 + this.formatCommand(commands); + // + logRecorder.info("{} {} start exec", DateUtil.now(), item.getName()); + try { + String s = sshService.exec(item, commands); + logRecorder.info(s); + } catch (Exception e) { + this.pubLog(item.getName() + " 执行异常", e); + } + } - /** - * 差异上传发布 - * - * @param nodeModel 节点 - * @param projectId 项目ID - * @param afterOpt 发布后的操作 - */ - private void diffSyncProject(NodeModel nodeModel, String projectId, AfterOpt afterOpt, boolean clearOld) { - File resultFile = this.resultFile; - String resultFileParent = resultFile.isFile() ? - FileUtil.getAbsolutePath(resultFile.getParent()) : FileUtil.getAbsolutePath(this.resultFile); - // - List files = FileUtil.loopFiles(resultFile); - List collect = files.stream().map(file -> { - // - JSONObject jsonObject = new JSONObject(); - jsonObject.put("name", StringUtil.delStartPath(file, resultFileParent, true)); - jsonObject.put("sha1", SecureUtil.sha1(file)); - return jsonObject; - }).collect(Collectors.toList()); - // - JSONObject jsonObject = new JSONObject(); - jsonObject.put("id", projectId); - jsonObject.put("data", collect); - JsonMessage requestBody = NodeForward.requestBody(nodeModel, NodeUrl.MANAGE_FILE_DIFF_FILE, this.userModel, jsonObject); - if (requestBody.getCode() != HttpStatus.HTTP_OK) { - throw new JpomRuntimeException("对比项目文件失败:" + requestBody); - } - JSONObject data = requestBody.getData(); - JSONArray diff = data.getJSONArray("diff"); - JSONArray del = data.getJSONArray("del"); - int delSize = CollUtil.size(del); - int diffSize = CollUtil.size(diff); - if (clearOld) { - logRecorder.info(StrUtil.format("对比文件结果,产物文件 {} 个、需要上传 {} 个、需要删除 {} 个", CollUtil.size(collect), CollUtil.size(diff), delSize)); - } else { - logRecorder.info(StrUtil.format("对比文件结果,产物文件 {} 个、需要上传 {} 个", CollUtil.size(collect), CollUtil.size(diff))); - } - // 清空发布才先执行删除 - if (delSize > 0 && clearOld) { - jsonObject.put("data", del); - requestBody = NodeForward.requestBody(nodeModel, NodeUrl.MANAGE_FILE_BATCH_DELETE, this.userModel, jsonObject); - if (requestBody.getCode() != HttpStatus.HTTP_OK) { - throw new JpomRuntimeException("删除项目文件失败:" + requestBody); - } - } - for (int i = 0; i < diffSize; i++) { - boolean last = (i == diffSize - 1); - JSONObject diffData = (JSONObject) diff.get(i); - String name = diffData.getString("name"); - File file = FileUtil.file(resultFileParent, name); - // - String startPath = StringUtil.delStartPath(file, resultFileParent, false); - // - JsonMessage jsonMessage = OutGivingRun.fileUpload(file, startPath, - projectId, false, last ? afterOpt : AfterOpt.No, nodeModel, this.userModel, false); - if (jsonMessage.getCode() != HttpStatus.HTTP_OK) { - throw new JpomRuntimeException("同步项目文件失败:" + jsonMessage); - } - if (last) { - // 最后一个 - logRecorder.info("发布项目包成功:" + jsonMessage); - } - } - } + /** + * 差异上传发布 + * + * @param nodeModel 节点 + * @param projectId 项目ID + * @param afterOpt 发布后的操作 + */ + private void diffSyncProject(NodeModel nodeModel, String projectId, AfterOpt afterOpt, boolean clearOld) { + File resultFile = this.resultFile; + String resultFileParent = resultFile.isFile() ? + FileUtil.getAbsolutePath(resultFile.getParent()) : FileUtil.getAbsolutePath(this.resultFile); + // + List files = FileUtil.loopFiles(resultFile); + List collect = files.stream().map(file -> { + // + JSONObject jsonObject = new JSONObject(); + jsonObject.put("name", StringUtil.delStartPath(file, resultFileParent, true)); + jsonObject.put("sha1", SecureUtil.sha1(file)); + return jsonObject; + }).collect(Collectors.toList()); + // + JSONObject jsonObject = new JSONObject(); + jsonObject.put("id", projectId); + jsonObject.put("data", collect); + JsonMessage requestBody = NodeForward.requestBody(nodeModel, NodeUrl.MANAGE_FILE_DIFF_FILE, this.userModel, jsonObject); + if (requestBody.getCode() != HttpStatus.HTTP_OK) { + throw new JpomRuntimeException("对比项目文件失败:" + requestBody); + } + JSONObject data = requestBody.getData(); + JSONArray diff = data.getJSONArray("diff"); + JSONArray del = data.getJSONArray("del"); + int delSize = CollUtil.size(del); + int diffSize = CollUtil.size(diff); + if (clearOld) { + logRecorder.info(StrUtil.format("对比文件结果,产物文件 {} 个、需要上传 {} 个、需要删除 {} 个", CollUtil.size(collect), CollUtil.size(diff), delSize)); + } else { + logRecorder.info(StrUtil.format("对比文件结果,产物文件 {} 个、需要上传 {} 个", CollUtil.size(collect), CollUtil.size(diff))); + } + // 清空发布才先执行删除 + if (delSize > 0 && clearOld) { + jsonObject.put("data", del); + requestBody = NodeForward.requestBody(nodeModel, NodeUrl.MANAGE_FILE_BATCH_DELETE, this.userModel, jsonObject); + if (requestBody.getCode() != HttpStatus.HTTP_OK) { + throw new JpomRuntimeException("删除项目文件失败:" + requestBody); + } + } + for (int i = 0; i < diffSize; i++) { + boolean last = (i == diffSize - 1); + JSONObject diffData = (JSONObject) diff.get(i); + String name = diffData.getString("name"); + File file = FileUtil.file(resultFileParent, name); + // + String startPath = StringUtil.delStartPath(file, resultFileParent, false); + // + JsonMessage jsonMessage = OutGivingRun.fileUpload(file, startPath, + projectId, false, last ? afterOpt : AfterOpt.No, nodeModel, this.userModel, false); + if (jsonMessage.getCode() != HttpStatus.HTTP_OK) { + throw new JpomRuntimeException("同步项目文件失败:" + jsonMessage); + } + if (last) { + // 最后一个 + logRecorder.info("发布项目包成功:" + jsonMessage); + } + } + } - /** - * 发布项目 - */ - private void doProject() { + /** + * 发布项目 + */ + private void doProject() { // AfterOpt afterOpt, boolean clearOld, boolean diffSync - AfterOpt afterOpt = BaseEnum.getEnum(AfterOpt.class, this.buildExtraModule.getAfterOpt(), AfterOpt.No); - boolean clearOld = this.buildExtraModule.isClearOld(); - boolean diffSync = this.buildExtraModule.isDiffSync(); - String releaseMethodDataId = this.buildExtraModule.getReleaseMethodDataId(); - String[] strings = StrUtil.splitToArray(releaseMethodDataId, CharPool.COLON); - if (ArrayUtil.length(strings) != 2) { - throw new IllegalArgumentException(releaseMethodDataId + " error"); - } - NodeService nodeService = SpringUtil.getBean(NodeService.class); - NodeModel nodeModel = nodeService.getByKey(strings[0]); - Objects.requireNonNull(nodeModel, "节点不存在"); - String projectId = strings[1]; - if (diffSync) { - this.diffSyncProject(nodeModel, projectId, afterOpt, clearOld); - return; - } - File zipFile = BuildUtil.isDirPackage(this.resultFile); - boolean unZip = true; - if (zipFile == null) { - zipFile = this.resultFile; - unZip = false; - } - JsonMessage jsonMessage = OutGivingRun.fileUpload(zipFile, null, - projectId, - unZip, - afterOpt, - nodeModel, this.userModel, clearOld); - if (jsonMessage.getCode() == HttpStatus.HTTP_OK) { - logRecorder.info("发布项目包成功:" + jsonMessage); - } else { - throw new JpomRuntimeException("发布项目包失败:" + jsonMessage); - } - } + AfterOpt afterOpt = BaseEnum.getEnum(AfterOpt.class, this.buildExtraModule.getAfterOpt(), AfterOpt.No); + boolean clearOld = this.buildExtraModule.isClearOld(); + boolean diffSync = this.buildExtraModule.isDiffSync(); + String releaseMethodDataId = this.buildExtraModule.getReleaseMethodDataId(); + String[] strings = StrUtil.splitToArray(releaseMethodDataId, CharPool.COLON); + if (ArrayUtil.length(strings) != 2) { + throw new IllegalArgumentException(releaseMethodDataId + " error"); + } + NodeService nodeService = SpringUtil.getBean(NodeService.class); + NodeModel nodeModel = nodeService.getByKey(strings[0]); + Objects.requireNonNull(nodeModel, "节点不存在"); + String projectId = strings[1]; + if (diffSync) { + this.diffSyncProject(nodeModel, projectId, afterOpt, clearOld); + return; + } + File zipFile = BuildUtil.isDirPackage(this.resultFile); + boolean unZip = true; + if (zipFile == null) { + zipFile = this.resultFile; + unZip = false; + } + JsonMessage jsonMessage = OutGivingRun.fileUpload(zipFile, null, + projectId, + unZip, + afterOpt, + nodeModel, this.userModel, clearOld); + if (jsonMessage.getCode() == HttpStatus.HTTP_OK) { + logRecorder.info("发布项目包成功:" + jsonMessage); + } else { + throw new JpomRuntimeException("发布项目包失败:" + jsonMessage); + } + } - /** - * 分发包 - */ - private void doOutGiving() { - String releaseMethodDataId = this.buildExtraModule.getReleaseMethodDataId(); - File zipFile = BuildUtil.isDirPackage(this.resultFile); - boolean unZip = true; - if (zipFile == null) { - zipFile = this.resultFile; - unZip = false; - } - OutGivingRun.startRun(releaseMethodDataId, zipFile, userModel, unZip); - logRecorder.info("开始执行分发包啦,请到分发中查看当前状态"); - } + /** + * 分发包 + */ + private void doOutGiving() { + String releaseMethodDataId = this.buildExtraModule.getReleaseMethodDataId(); + File zipFile = BuildUtil.isDirPackage(this.resultFile); + boolean unZip = true; + if (zipFile == null) { + zipFile = this.resultFile; + unZip = false; + } + OutGivingRun.startRun(releaseMethodDataId, zipFile, userModel, unZip); + logRecorder.info("开始执行分发包啦,请到分发中查看当前状态"); + } - /** - * 发布异常日志 - * - * @param title 描述 - * @param throwable 异常 - */ - private void pubLog(String title, Throwable throwable) { - logRecorder.error(title, throwable); - this.updateStatus(BuildStatus.PubError); - } + /** + * 发布异常日志 + * + * @param title 描述 + * @param throwable 异常 + */ + private void pubLog(String title, Throwable throwable) { + logRecorder.error(title, throwable); + this.updateStatus(BuildStatus.PubError); + } - @Override - public void run() { - this.start(); - } + @Override + public void run() { + this.start(); + } } diff --git a/modules/server/src/main/java/io/jpom/socket/ScriptProcessBuilder.java b/modules/server/src/main/java/io/jpom/socket/ScriptProcessBuilder.java index 4ff3cb9af..5cfa635ec 100644 --- a/modules/server/src/main/java/io/jpom/socket/ScriptProcessBuilder.java +++ b/modules/server/src/main/java/io/jpom/socket/ScriptProcessBuilder.java @@ -30,7 +30,6 @@ import cn.hutool.core.io.LineHandler; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.StrUtil; -import cn.hutool.system.SystemUtil; import cn.jiangzeyin.common.DefaultSystemLog; import cn.jiangzeyin.common.JsonMessage; import cn.jiangzeyin.common.spring.SpringUtil; @@ -55,177 +54,175 @@ import java.util.concurrent.ConcurrentHashMap; * @date 2022/1/19 */ public class ScriptProcessBuilder extends BaseRunScript implements Runnable { - /** - * 执行中的缓存 - */ - private static final ConcurrentHashMap FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>(); + /** + * 执行中的缓存 + */ + private static final ConcurrentHashMap FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP = new ConcurrentHashMap<>(); - private final ProcessBuilder processBuilder; - private final Set sessions = new HashSet<>(); - private final String executeId; + private final ProcessBuilder processBuilder; + private final Set sessions = new HashSet<>(); + private final String executeId; - private ScriptProcessBuilder(ScriptModel nodeScriptModel, String executeId, String args) { - super(nodeScriptModel.logFile(executeId)); - this.executeId = executeId; - // - WorkspaceEnvVarService workspaceEnvVarService = SpringUtil.getBean(WorkspaceEnvVarService.class); - Map env = workspaceEnvVarService.getEnv(nodeScriptModel.getWorkspaceId()); + private ScriptProcessBuilder(ScriptModel nodeScriptModel, String executeId, String args) { + super(nodeScriptModel.logFile(executeId)); + this.executeId = executeId; + // + WorkspaceEnvVarService workspaceEnvVarService = SpringUtil.getBean(WorkspaceEnvVarService.class); + Map env = workspaceEnvVarService.getEnv(nodeScriptModel.getWorkspaceId()); - File scriptFile = nodeScriptModel.scriptFile(); - // - String script = FileUtil.getAbsolutePath(scriptFile); - processBuilder = new ProcessBuilder(); - List command = StrUtil.splitTrim(args, StrUtil.SPACE); - command.add(0, script); - if (SystemUtil.getOsInfo().isLinux() || SystemUtil.getOsInfo().isMac()) { - command.add(0, CommandUtil.SUFFIX); - } - DefaultSystemLog.getLog().debug(CollUtil.join(command, StrUtil.SPACE)); - processBuilder.redirectErrorStream(true); - processBuilder.command(command); - Map environment = processBuilder.environment(); - environment.putAll(env); - processBuilder.directory(scriptFile.getParentFile()); - } + File scriptFile = nodeScriptModel.scriptFile(); + // + String script = FileUtil.getAbsolutePath(scriptFile); + processBuilder = new ProcessBuilder(); + List command = StrUtil.splitTrim(args, StrUtil.SPACE); + command.add(0, script); + command.add(0, CommandUtil.EXECUTE_PREFIX); + DefaultSystemLog.getLog().debug(CollUtil.join(command, StrUtil.SPACE)); + processBuilder.redirectErrorStream(true); + processBuilder.command(command); + Map environment = processBuilder.environment(); + environment.putAll(env); + processBuilder.directory(scriptFile.getParentFile()); + } - /** - * 创建执行 并监听 - * - * @param nodeScriptModel 脚本模版 - * @param executeId 执行ID - * @param args 参数 - */ - public static ScriptProcessBuilder create(ScriptModel nodeScriptModel, String executeId, String args) { - return FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.computeIfAbsent(executeId, file1 -> { - ScriptProcessBuilder scriptProcessBuilder1 = new ScriptProcessBuilder(nodeScriptModel, executeId, args); - ThreadUtil.execute(scriptProcessBuilder1); - return scriptProcessBuilder1; - }); - } + /** + * 创建执行 并监听 + * + * @param nodeScriptModel 脚本模版 + * @param executeId 执行ID + * @param args 参数 + */ + public static ScriptProcessBuilder create(ScriptModel nodeScriptModel, String executeId, String args) { + return FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.computeIfAbsent(executeId, file1 -> { + ScriptProcessBuilder scriptProcessBuilder1 = new ScriptProcessBuilder(nodeScriptModel, executeId, args); + ThreadUtil.execute(scriptProcessBuilder1); + return scriptProcessBuilder1; + }); + } - /** - * 创建执行 并监听 - * - * @param nodeScriptModel 脚本模版 - * @param executeId 执行ID - * @param args 参数 - * @param session 会话 - */ - public static void addWatcher(ScriptModel nodeScriptModel, String executeId, String args, WebSocketSession session) { - ScriptProcessBuilder scriptProcessBuilder = create(nodeScriptModel, executeId, args); - // - if (scriptProcessBuilder.sessions.add(session)) { - if (FileUtil.exist(scriptProcessBuilder.logFile)) { - // 读取之前的信息并发送 - FileUtil.readLines(scriptProcessBuilder.logFile, CharsetUtil.CHARSET_UTF_8, (LineHandler) line -> { - try { - SocketSessionUtil.send(session, line); - } catch (IOException e) { - DefaultSystemLog.getLog().error("发送消息失败", e); - } - }); - } - } - } + /** + * 创建执行 并监听 + * + * @param nodeScriptModel 脚本模版 + * @param executeId 执行ID + * @param args 参数 + * @param session 会话 + */ + public static void addWatcher(ScriptModel nodeScriptModel, String executeId, String args, WebSocketSession session) { + ScriptProcessBuilder scriptProcessBuilder = create(nodeScriptModel, executeId, args); + // + if (scriptProcessBuilder.sessions.add(session)) { + if (FileUtil.exist(scriptProcessBuilder.logFile)) { + // 读取之前的信息并发送 + FileUtil.readLines(scriptProcessBuilder.logFile, CharsetUtil.CHARSET_UTF_8, (LineHandler) line -> { + try { + SocketSessionUtil.send(session, line); + } catch (IOException e) { + DefaultSystemLog.getLog().error("发送消息失败", e); + } + }); + } + } + } - /** - * 判断是否还在执行中 - * - * @param executeId 执行id - * @return true 还在执行 - */ - public static boolean isRun(String executeId) { - return FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.containsKey(executeId); - } + /** + * 判断是否还在执行中 + * + * @param executeId 执行id + * @return true 还在执行 + */ + public static boolean isRun(String executeId) { + return FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.containsKey(executeId); + } - /** - * 关闭会话 - * - * @param session 会话 - */ - public static void stopWatcher(WebSocketSession session) { - Collection scriptProcessBuilders = FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.values(); - for (ScriptProcessBuilder scriptProcessBuilder : scriptProcessBuilders) { - Set sessions = scriptProcessBuilder.sessions; - sessions.removeIf(session1 -> session1.getId().equals(session.getId())); - } - } + /** + * 关闭会话 + * + * @param session 会话 + */ + public static void stopWatcher(WebSocketSession session) { + Collection scriptProcessBuilders = FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.values(); + for (ScriptProcessBuilder scriptProcessBuilder : scriptProcessBuilders) { + Set sessions = scriptProcessBuilder.sessions; + sessions.removeIf(session1 -> session1.getId().equals(session.getId())); + } + } - /** - * 停止脚本命令 - * - * @param executeId 执行ID - */ - public static void stopRun(String executeId) { - ScriptProcessBuilder scriptProcessBuilder = FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.get(executeId); - if (scriptProcessBuilder != null) { - scriptProcessBuilder.end("停止运行"); - } - } + /** + * 停止脚本命令 + * + * @param executeId 执行ID + */ + public static void stopRun(String executeId) { + ScriptProcessBuilder scriptProcessBuilder = FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.get(executeId); + if (scriptProcessBuilder != null) { + scriptProcessBuilder.end("停止运行"); + } + } - @Override - public void run() { - //初始化ProcessBuilder对象 - try { - this.handle("start execute:" + DateUtil.now()); - process = processBuilder.start(); - { - inputStream = process.getInputStream(); - IoUtil.readLines(inputStream, ExtConfigBean.getInstance().getConsoleLogCharset(), (LineHandler) ScriptProcessBuilder.this::handle); - } - int waitFor = process.waitFor(); - JsonMessage jsonMessage = new JsonMessage<>(200, "执行完毕:" + waitFor); - JSONObject jsonObject = jsonMessage.toJson(); - jsonObject.put("op", ConsoleCommandOp.stop.name()); - this.end(jsonObject.toString()); - this.handle("execute done:" + waitFor + " time:" + DateUtil.now()); - } catch (Exception e) { - DefaultSystemLog.getLog().error("执行异常", e); - this.end("执行异常:" + e.getMessage()); - } finally { - this.close(); - } - } + @Override + public void run() { + //初始化ProcessBuilder对象 + try { + this.handle("start execute:" + DateUtil.now()); + process = processBuilder.start(); + { + inputStream = process.getInputStream(); + IoUtil.readLines(inputStream, ExtConfigBean.getInstance().getConsoleLogCharset(), (LineHandler) ScriptProcessBuilder.this::handle); + } + int waitFor = process.waitFor(); + JsonMessage jsonMessage = new JsonMessage<>(200, "执行完毕:" + waitFor); + JSONObject jsonObject = jsonMessage.toJson(); + jsonObject.put("op", ConsoleCommandOp.stop.name()); + this.end(jsonObject.toString()); + this.handle("execute done:" + waitFor + " time:" + DateUtil.now()); + } catch (Exception e) { + DefaultSystemLog.getLog().error("执行异常", e); + this.end("执行异常:" + e.getMessage()); + } finally { + this.close(); + } + } - /** - * 结束执行 - * - * @param msg 响应的消息 - */ - @Override - protected void end(String msg) { - Iterator iterator = sessions.iterator(); - while (iterator.hasNext()) { - WebSocketSession session = iterator.next(); - try { - SocketSessionUtil.send(session, msg); - } catch (IOException e) { - DefaultSystemLog.getLog().error("发送消息失败", e); - } - iterator.remove(); - } - FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.remove(this.executeId); - } + /** + * 结束执行 + * + * @param msg 响应的消息 + */ + @Override + protected void end(String msg) { + Iterator iterator = sessions.iterator(); + while (iterator.hasNext()) { + WebSocketSession session = iterator.next(); + try { + SocketSessionUtil.send(session, msg); + } catch (IOException e) { + DefaultSystemLog.getLog().error("发送消息失败", e); + } + iterator.remove(); + } + FILE_SCRIPT_PROCESS_BUILDER_CONCURRENT_HASH_MAP.remove(this.executeId); + } - /** - * 响应 - * - * @param line 信息 - */ - @Override - protected void handle(String line) { - super.handle(line); - // - Iterator iterator = sessions.iterator(); - while (iterator.hasNext()) { - WebSocketSession session = iterator.next(); - try { - SocketSessionUtil.send(session, line); - } catch (IOException e) { - DefaultSystemLog.getLog().error("发送消息失败", e); - iterator.remove(); - } - } - } + /** + * 响应 + * + * @param line 信息 + */ + @Override + protected void handle(String line) { + super.handle(line); + // + Iterator iterator = sessions.iterator(); + while (iterator.hasNext()) { + WebSocketSession session = iterator.next(); + try { + SocketSessionUtil.send(session, line); + } catch (IOException e) { + DefaultSystemLog.getLog().error("发送消息失败", e); + iterator.remove(); + } + } + } } diff --git a/web-vue/src/pages/script/script-list.vue b/web-vue/src/pages/script/script-list.vue index 62ccf2b96..afde39c66 100644 --- a/web-vue/src/pages/script/script-list.vue +++ b/web-vue/src/pages/script/script-list.vue @@ -1,7 +1,7 @@