diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/dto/ExecCommandDTO.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/dto/ExecCommandDTO.java index a8b4244d..909c9dd1 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/dto/ExecCommandDTO.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/dto/ExecCommandDTO.java @@ -25,13 +25,25 @@ public class ExecCommandDTO { @Schema(description = "hostId") private Long logId; + @Schema(description = "用户id") + private Long userId; + + @Schema(description = "用户名") + private String username; + + @Schema(description = "执行描述") + private String description; + + @Schema(description = "执行序列") + private Integer execSeq; + @Schema(description = "超时时间") private Integer timeout; @Schema(description = "是否使用脚本执行") private Boolean scriptExec; - @Schema(description = "主机") + @Schema(description = "执行主机") private List hosts; } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/dto/ExecCommandHostDTO.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/dto/ExecCommandHostDTO.java index 397b0459..0652d0f9 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/dto/ExecCommandHostDTO.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/dto/ExecCommandHostDTO.java @@ -26,6 +26,12 @@ public class ExecCommandHostDTO { @Schema(description = "hostId") private Long hostId; + @Schema(description = "主机名称") + private String hostName; + + @Schema(description = "主机地址") + private String hostAddress; + @Schema(description = "日志文件路径") private String logPath; @@ -35,6 +41,9 @@ public class ExecCommandHostDTO { @Schema(description = "执行命令") private String command; + @Schema(description = "主机用户") + private String username; + @Schema(description = "命令编码") private String charset; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecCommandHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/BaseExecCommandHandler.java similarity index 74% rename from orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecCommandHandler.java rename to orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/BaseExecCommandHandler.java index 425d3380..86f3187f 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecCommandHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/BaseExecCommandHandler.java @@ -10,6 +10,7 @@ import com.orion.lang.support.timeout.TimeoutEndpoint; import com.orion.lang.utils.Booleans; import com.orion.lang.utils.Exceptions; import com.orion.lang.utils.Strings; +import com.orion.lang.utils.ansi.AnsiAppender; import com.orion.lang.utils.io.Streams; import com.orion.net.host.SessionStore; import com.orion.net.host.sftp.SftpExecutor; @@ -32,14 +33,14 @@ import java.util.Date; import java.util.concurrent.TimeUnit; /** - * 命令执行器 + * 命令执行器 基类 * * @author Jiahang Li * @version 1.0.0 - * @since 2024/3/12 11:30 + * @since 2024/4/25 18:35 */ @Slf4j -public class ExecCommandHandler implements IExecCommandHandler { +public abstract class BaseExecCommandHandler implements IExecCommandHandler { private final FileClient fileClient = SpringHolder.getBean("logsFileClient"); @@ -49,32 +50,35 @@ public class ExecCommandHandler implements IExecCommandHandler { private final ExecHostLogDAO execHostLogDAO = SpringHolder.getBean(ExecHostLogDAO.class); - private final ExecCommandDTO execCommand; + protected final ExecCommandDTO execCommand; - private final ExecCommandHostDTO execHostCommand; + protected final ExecCommandHostDTO execHostCommand; private final TimeoutChecker timeoutChecker; @Getter - private ExecHostStatusEnum status; + protected ExecHostStatusEnum status; + + protected ExecHostLogDO updateRecord; + + private OutputStream logOutputStream; private SessionStore sessionStore; private CommandExecutor executor; - private OutputStream logOutputStream; - private volatile boolean closed; private volatile boolean interrupted; - public ExecCommandHandler(ExecCommandDTO execCommand, - ExecCommandHostDTO execHostCommand, - TimeoutChecker timeoutChecker) { + public BaseExecCommandHandler(ExecCommandDTO execCommand, + ExecCommandHostDTO execHostCommand, + TimeoutChecker timeoutChecker) { this.status = ExecHostStatusEnum.WAITING; this.execCommand = execCommand; this.execHostCommand = execHostCommand; this.timeoutChecker = timeoutChecker; + this.updateRecord = new ExecHostLogDO(); } @Override @@ -91,23 +95,25 @@ public class ExecCommandHandler implements IExecCommandHandler { } catch (Exception e) { log.error("ExecCommandHandler run error id: {}", id, e); ex = e; + } + // 执行完成回调 + try { + // 回调 + this.onFinishCallback(ex); } finally { + // 释放资源 Streams.close(this); } - // 执行回调 - if (this.interrupted) { - // 中断执行 - this.updateStatus(ExecHostStatusEnum.INTERRUPTED, null); - } else if (ex != null) { - // 执行失败 - this.updateStatus(ExecHostStatusEnum.FAILED, ex); - } else if (executor.isTimeout()) { - // 更新执行超时 - this.updateStatus(ExecHostStatusEnum.TIMEOUT, null); - } else { - // 更新执行完成 - this.updateStatus(ExecHostStatusEnum.COMPLETED, null); - } + } + + /** + * 初始化日志输出流 + * + * @throws Exception Exception + */ + protected void initLogOutputStream() throws Exception { + // 打开日志流 + this.logOutputStream = fileClient.getContentOutputStream(execHostCommand.getLogPath()); } /** @@ -115,9 +121,9 @@ public class ExecCommandHandler implements IExecCommandHandler { * * @throws IOException IOException */ - private void execCommand() throws Exception { - // 打开日志流 - this.logOutputStream = fileClient.getContentOutputStream(execHostCommand.getLogPath()); + protected void execCommand() throws Exception { + // 初始化日志 + this.initLogOutputStream(); // 打开会话 this.sessionStore = hostTerminalService.openSessionStore(execHostCommand.getHostId()); if (Booleans.isTrue(execCommand.getScriptExec())) { @@ -141,7 +147,7 @@ public class ExecCommandHandler implements IExecCommandHandler { /** * 上传脚本文件 */ - private void uploadScriptFile() { + protected void uploadScriptFile() { SftpExecutor sftpExecutor = null; try { // 打开 sftp @@ -166,6 +172,42 @@ public class ExecCommandHandler implements IExecCommandHandler { } } + /** + * 执行完成回调 + * + * @param e e + */ + protected void onFinishCallback(Exception e) { + // 执行回调 + if (this.interrupted) { + // 中断执行 + this.updateStatus(ExecHostStatusEnum.INTERRUPTED, null); + } else if (e != null) { + // 执行失败 + this.updateStatus(ExecHostStatusEnum.FAILED, e); + } else if (executor.isTimeout()) { + // 更新执行超时 + this.updateStatus(ExecHostStatusEnum.TIMEOUT, null); + } else { + // 更新执行完成 + this.updateStatus(ExecHostStatusEnum.COMPLETED, null); + } + } + + /** + * 拼接日志 + * + * @param appender appender + */ + protected void appendLog(AnsiAppender appender) { + try { + logOutputStream.write(Strings.bytes(appender.toString())); + logOutputStream.flush(); + } catch (Exception e) { + log.error("BaseExecCommandHandler.appendLog error", e); + } + } + /** * 更新状态 * @@ -176,30 +218,29 @@ public class ExecCommandHandler implements IExecCommandHandler { this.status = status; Long id = execHostCommand.getHostLogId(); String statusName = status.name(); - log.info("ExecCommandHandler.updateStatus start id: {}, status: {}", id, statusName); - ExecHostLogDO update = new ExecHostLogDO(); - update.setId(id); - update.setStatus(statusName); + log.info("BaseExecCommandHandler.updateStatus start id: {}, status: {}", id, statusName); + updateRecord.setId(id); + updateRecord.setStatus(statusName); if (ExecHostStatusEnum.RUNNING.equals(status)) { // 运行中 - update.setStartTime(new Date()); + updateRecord.setStartTime(new Date()); } else if (ExecHostStatusEnum.COMPLETED.equals(status)) { // 完成 - update.setFinishTime(new Date()); - update.setExitStatus(executor.getExitCode()); + updateRecord.setFinishTime(new Date()); + updateRecord.setExitStatus(executor.getExitCode()); } else if (ExecHostStatusEnum.FAILED.equals(status)) { // 失败 - update.setFinishTime(new Date()); - update.setErrorMessage(this.getErrorMessage(ex)); + updateRecord.setFinishTime(new Date()); + updateRecord.setErrorMessage(this.getErrorMessage(ex)); } else if (ExecHostStatusEnum.TIMEOUT.equals(status)) { // 超时 - update.setFinishTime(new Date()); + updateRecord.setFinishTime(new Date()); } else if (ExecHostStatusEnum.INTERRUPTED.equals(status)) { // 中断 - update.setFinishTime(new Date()); + updateRecord.setFinishTime(new Date()); } - int effect = execHostLogDAO.updateById(update); - log.info("ExecCommandHandler.updateStatus finish id: {}, effect: {}", id, effect); + int effect = execHostLogDAO.updateById(updateRecord); + log.info("BaseExecCommandHandler.updateStatus finish id: {}, effect: {}", id, effect); } @Override @@ -208,20 +249,21 @@ public class ExecCommandHandler implements IExecCommandHandler { } @Override - public void interrupted() { - log.info("ExecCommandHandler.interrupted id: {}, interrupted: {}, closed: {}", + public void interrupt() { + log.info("BaseExecCommandHandler.interrupt id: {}, interrupted: {}, closed: {}", execHostCommand.getHostLogId(), interrupted, closed); if (this.interrupted || this.closed) { return; } // 关闭 this.interrupted = true; - this.close(); + Streams.close(executor); + Streams.close(sessionStore); } @Override public void close() { - log.info("ExecCommandHandler.closed id: {}, closed: {}", + log.info("BaseExecCommandHandler.closed id: {}, closed: {}", execHostCommand.getHostLogId(), closed); if (this.closed) { return; @@ -239,7 +281,7 @@ public class ExecCommandHandler implements IExecCommandHandler { * @param ex ex * @return errorMessage */ - private String getErrorMessage(Exception ex) { + protected String getErrorMessage(Exception ex) { String message; if (ex instanceof InvalidArgumentException) { message = ex.getMessage(); diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecCommandAnsiHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecCommandAnsiHandler.java new file mode 100644 index 00000000..620399b0 --- /dev/null +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecCommandAnsiHandler.java @@ -0,0 +1,177 @@ +package com.orion.ops.module.asset.handler.host.exec.command.handler; + +import com.orion.lang.support.timeout.TimeoutChecker; +import com.orion.lang.support.timeout.TimeoutEndpoint; +import com.orion.lang.utils.Booleans; +import com.orion.lang.utils.ansi.AnsiAppender; +import com.orion.lang.utils.ansi.style.AnsiFont; +import com.orion.lang.utils.ansi.style.color.AnsiForeground; +import com.orion.lang.utils.time.Dates; +import com.orion.net.host.ssh.ExitCode; +import com.orion.ops.framework.common.constant.Const; +import com.orion.ops.module.asset.enums.ExecHostStatusEnum; +import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandDTO; +import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandHostDTO; + +/** + * 命令执行器 ansi 日志输出 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/4/25 18:19 + */ +public class ExecCommandAnsiHandler extends BaseExecCommandHandler { + + public ExecCommandAnsiHandler(ExecCommandDTO execCommand, ExecCommandHostDTO execHostCommand, TimeoutChecker timeoutChecker) { + super(execCommand, execHostCommand, timeoutChecker); + } + + @Override + protected void initLogOutputStream() throws Exception { + super.initLogOutputStream(); + // 拼接启动日志 + AnsiAppender appender = AnsiAppender.create() + .append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "> 准备执行命令 ") + .append(Dates.current()) + .newLine() + .append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "执行记录: ") + .append(execCommand.getLogId()) + .newLine() + .append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "执行描述: ") + .append(execCommand.getDescription()) + .newLine() + .append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "执行用户: ") + .append(execCommand.getUsername()); + // 非系统用户执行添加 userId + if (Const.SYSTEM_USER_ID.equals(execCommand.getUserId())) { + appender.newLine(); + } else { + appender.append(" (") + .append(execCommand.getUserId()) + .append(")") + .newLine(); + } + // 执行序列 + if (execCommand.getExecSeq() != null) { + appender.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "执行序列: ") + .append('#') + .append(execCommand.getExecSeq()) + .newLine(); + } + appender.append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "执行主机: ") + .append(execHostCommand.getHostName()) + .append(" (") + .append(execHostCommand.getHostId()) + .append(")") + .newLine() + .append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "主机地址: ") + .append(execHostCommand.getHostAddress()) + .newLine() + .append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "超时时间: ") + .append(execCommand.getTimeout()) + .newLine() + .append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "脚本执行: ") + .append(execCommand.getScriptExec()) + .newLine() + .newLine() + .append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "> 执行命令 ") + .newLine() + .append(execHostCommand.getCommand()) + .newLine() + .newLine(); + // 非脚本执行拼接开始执行日志 + if (!Booleans.isTrue(execCommand.getScriptExec())) { + appender.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "> 开始执行命令 ") + .append(Dates.current()) + .newLine(); + } + this.appendLog(appender); + } + + @Override + protected void uploadScriptFile() { + try { + // 拼接上传日志 + AnsiAppender startAppender = AnsiAppender.create() + .newLine() + .append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "> 准备上传脚本 ") + .append(Dates.current()) + .newLine() + .append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "文件路径: ") + .append(execHostCommand.getScriptPath()) + .newLine(); + this.appendLog(startAppender); + // 上传脚本文件 + super.uploadScriptFile(); + // 拼接完成日志 + AnsiAppender finishAppender = AnsiAppender.create() + .append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "< 脚本上传成功 ") + .append(Dates.current()) + .newLine() + .newLine() + .append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "> 开始执行脚本 ") + .append(Dates.current()) + .newLine(); + this.appendLog(finishAppender); + } catch (Exception e) { + // 拼接失败日志 + AnsiAppender errorAppender = AnsiAppender.create() + .append(AnsiForeground.BRIGHT_RED.and(AnsiFont.BOLD), "< 脚本上传失败 ") + .append(Dates.current()) + .newLine(); + this.appendLog(errorAppender); + throw e; + } + } + + @Override + protected void onFinishCallback(Exception e) { + // 执行完成回调 + super.onFinishCallback(e); + // 拼接日志 + AnsiAppender appender = AnsiAppender.create() + .newLine(); + if (this.status == ExecHostStatusEnum.INTERRUPTED) { + // 中断执行 + appender.append(AnsiForeground.BRIGHT_YELLOW.and(AnsiFont.BOLD), "< 命令执行中断 ") + .append(Dates.current()) + .newLine(); + } else if (this.status == ExecHostStatusEnum.FAILED) { + // 执行失败 + appender.append(AnsiForeground.BRIGHT_RED.and(AnsiFont.BOLD), "< 命令执行失败 ") + .append(Dates.current()) + .newLine() + .append(AnsiForeground.BRIGHT_RED.and(AnsiFont.BOLD), "错误原因: ") + .append(this.getErrorMessage(e)) + .newLine(); + } else if (this.status == ExecHostStatusEnum.TIMEOUT) { + // 更新执行超时 + appender.append(AnsiForeground.BRIGHT_YELLOW.and(AnsiFont.BOLD), "< 命令执行超时 ") + .append(Dates.current()) + .newLine(); + } else { + long ms = this.updateRecord.getFinishTime().getTime() - this.updateRecord.getStartTime().getTime(); + Integer exitStatus = this.updateRecord.getExitStatus(); + // 执行完成 + appender.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), "< 命令执行完成 ") + .append(Dates.current()) + .newLine() + .append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "exit: "); + if (ExitCode.isSuccess(exitStatus)) { + appender.append(AnsiForeground.BRIGHT_GREEN.and(AnsiFont.BOLD), exitStatus); + } else { + appender.append(AnsiForeground.BRIGHT_RED.and(AnsiFont.BOLD), exitStatus); + } + appender.newLine() + .append(AnsiForeground.BRIGHT_BLUE.and(AnsiFont.BOLD), "used: ") + .append(Dates.interval(ms, false, "d ", "h ", "m ", "s")) + .append(" (") + .append(ms) + .append(" ms)") + .newLine(); + } + // 拼接日志 + this.appendLog(appender); + } + +} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecCommandOriginHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecCommandOriginHandler.java new file mode 100644 index 00000000..0917dcae --- /dev/null +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecCommandOriginHandler.java @@ -0,0 +1,23 @@ +package com.orion.ops.module.asset.handler.host.exec.command.handler; + +import com.orion.lang.support.timeout.TimeoutChecker; +import com.orion.lang.support.timeout.TimeoutEndpoint; +import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandDTO; +import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandHostDTO; +import lombok.extern.slf4j.Slf4j; + +/** + * 命令执行器 原始日志输出 + * + * @author Jiahang Li + * @version 1.0.0 + * @since 2024/3/12 11:30 + */ +@Slf4j +public class ExecCommandOriginHandler extends BaseExecCommandHandler { + + public ExecCommandOriginHandler(ExecCommandDTO execCommand, ExecCommandHostDTO execHostCommand, TimeoutChecker timeoutChecker) { + super(execCommand, execHostCommand, timeoutChecker); + } + +} diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecTaskHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecTaskHandler.java index 585c2604..93d8ed93 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecTaskHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/ExecTaskHandler.java @@ -3,11 +3,13 @@ package com.orion.ops.module.asset.handler.host.exec.command.handler; import com.orion.lang.support.timeout.TimeoutChecker; import com.orion.lang.support.timeout.TimeoutCheckers; import com.orion.lang.support.timeout.TimeoutEndpoint; +import com.orion.lang.utils.Booleans; import com.orion.lang.utils.Threads; import com.orion.lang.utils.collect.Lists; import com.orion.lang.utils.io.Streams; import com.orion.ops.module.asset.dao.ExecLogDAO; import com.orion.ops.module.asset.define.AssetThreadPools; +import com.orion.ops.module.asset.define.config.AppExecLogConfig; import com.orion.ops.module.asset.entity.domain.ExecLogDO; import com.orion.ops.module.asset.enums.ExecStatusEnum; import com.orion.ops.module.asset.handler.host.exec.command.dto.ExecCommandDTO; @@ -34,6 +36,8 @@ public class ExecTaskHandler implements IExecTaskHandler { private static final ExecTaskManager execTaskManager = SpringHolder.getBean(ExecTaskManager.class); + private static final AppExecLogConfig appExecLogConfig = SpringHolder.getBean(AppExecLogConfig.class); + private final ExecCommandDTO execCommand; private TimeoutChecker timeoutChecker; @@ -73,9 +77,9 @@ public class ExecTaskHandler implements IExecTaskHandler { } @Override - public void interrupted() { - log.info("ExecTaskHandler-interrupted id: {}", execCommand.getLogId()); - handlers.forEach(IExecCommandHandler::interrupted); + public void interrupt() { + log.info("ExecTaskHandler-interrupt id: {}", execCommand.getLogId()); + handlers.forEach(IExecCommandHandler::interrupt); } /** @@ -93,18 +97,34 @@ public class ExecTaskHandler implements IExecTaskHandler { List hosts = execCommand.getHosts(); if (hosts.size() == 1) { // 单个主机直接执行 - ExecCommandHandler handler = new ExecCommandHandler(execCommand, hosts.get(0), timeoutChecker); + IExecCommandHandler handler = this.createCommandHandler(hosts.get(0)); handlers.add(handler); handler.run(); } else { hosts.stream() - .map(s -> new ExecCommandHandler(execCommand, s, timeoutChecker)) + .map(this::createCommandHandler) .forEach(handlers::add); // 多个主机异步阻塞执行 Threads.blockRun(handlers, AssetThreadPools.EXEC_HOST); } } + /** + * 创建命令执行器 + * + * @param host host + * @return handler + */ + private IExecCommandHandler createCommandHandler(ExecCommandHostDTO host) { + if (Booleans.isTrue(appExecLogConfig.getAppendAnsi())) { + // ansi 日志 + return new ExecCommandAnsiHandler(execCommand, host, timeoutChecker); + } else { + // 原始日志 + return new ExecCommandOriginHandler(execCommand, host, timeoutChecker); + } + } + /** * 更新状态 * diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/IExecCommandHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/IExecCommandHandler.java index 921cba9f..79f2c579 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/IExecCommandHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/IExecCommandHandler.java @@ -22,7 +22,7 @@ public interface IExecCommandHandler extends Runnable, SafeCloseable { /** * 中断执行 */ - void interrupted(); + void interrupt(); /** * 获取当前状态 diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/IExecTaskHandler.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/IExecTaskHandler.java index 21e43250..864f320b 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/IExecTaskHandler.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/exec/command/handler/IExecTaskHandler.java @@ -23,6 +23,6 @@ public interface IExecTaskHandler extends Runnable, SafeCloseable { /** * 中断执行 */ - void interrupted(); + void interrupt(); } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/session/SftpSession.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/session/SftpSession.java index 92080a0a..a1a06db3 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/session/SftpSession.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/terminal/session/SftpSession.java @@ -129,7 +129,7 @@ public class SftpSession extends TerminalSession implements ISftpSession { throw Exceptions.ioRuntime(e); } finally { // 同关闭 transfer downloader - // 关闭 inputStream 可能会被阻塞 ??..?? 只能关闭 executor + // 关闭 inputStream 可能会被阻塞 ???...??? 只能关闭 executor Streams.close(this.executor); this.connect(); } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/transfer/session/DownloadSession.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/transfer/session/DownloadSession.java index 9bb23073..2e3771b4 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/transfer/session/DownloadSession.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/handler/host/transfer/session/DownloadSession.java @@ -98,7 +98,7 @@ public class DownloadSession extends TransferHostSession implements IDownloadSes @Override protected void closeStream() { - // 关闭 inputStream 可能会被阻塞 ??..?? 只能关闭 executor + // 关闭 inputStream 可能会被阻塞 ???...??? 只能关闭 executor Streams.close(this.executor); this.executor = null; this.inputStream = null; diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecCommandServiceImpl.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecCommandServiceImpl.java index c24573f3..013db110 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecCommandServiceImpl.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecCommandServiceImpl.java @@ -197,9 +197,12 @@ public class ExecCommandServiceImpl implements ExecCommandService { return ExecCommandHostDTO.builder() .hostId(s.getHostId()) .hostLogId(s.getId()) + .hostName(s.getHostName()) + .hostAddress(s.getHostAddress()) .command(s.getCommand()) .logPath(s.getLogPath()) .scriptPath(s.getScriptPath()) + .username(config.getUsername()) .charset(config.getCharset()) .fileNameCharset(config.getFileNameCharset()) .fileContentCharset(config.getFileContentCharset()) @@ -208,6 +211,10 @@ public class ExecCommandServiceImpl implements ExecCommandService { // 执行信息 ExecCommandDTO exec = ExecCommandDTO.builder() .logId(execLog.getId()) + .userId(execLog.getUserId()) + .username(execLog.getUsername()) + .description(execLog.getDescription()) + .execSeq(execLog.getExecSeq()) .timeout(execLog.getTimeout()) .scriptExec(ScriptExecEnum.isEnabled(execLog.getScriptExec())) .hosts(hosts) diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecHostLogServiceImpl.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecHostLogServiceImpl.java index ed220ba2..1c12c844 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecHostLogServiceImpl.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecHostLogServiceImpl.java @@ -79,7 +79,7 @@ public class ExecHostLogServiceImpl implements ExecHostLogService { .flatMap(s -> s.stream() .filter(h -> h.getHostId().equals(record.getHostId())) .findFirst()) - .ifPresent(IExecCommandHandler::interrupted); + .ifPresent(IExecCommandHandler::interrupt); // 删除 int effect = execHostLogDAO.deleteById(id); log.info("ExecHostLogService-deleteExecHostLogById id: {}, effect: {}", id, effect); diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecLogServiceImpl.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecLogServiceImpl.java index 5510e7d5..110d33af 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecLogServiceImpl.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/service/impl/ExecLogServiceImpl.java @@ -176,7 +176,7 @@ public class ExecLogServiceImpl implements ExecLogService { ExecLogDO record = execLogDAO.selectByIdSource(id, source); Valid.notNull(record, ErrorMessage.DATA_ABSENT); // 中断命令执行 - this.interruptedTask(Lists.singleton(id)); + this.interruptTask(Lists.singleton(id)); // 删除执行日志 int effect = execLogDAO.deleteById(id); // 删除主机日志 @@ -200,7 +200,7 @@ public class ExecLogServiceImpl implements ExecLogService { .intValue(); Valid.isTrue(idList.size() == count, ErrorMessage.DATA_MODIFIED); // 中断命令执行 - this.interruptedTask(idList); + this.interruptTask(idList); // 删除执行日志 int effect = execLogDAO.deleteBatchIds(idList); // 删除主机日志 @@ -230,7 +230,7 @@ public class ExecLogServiceImpl implements ExecLogService { int effect = 0; if (!idList.isEmpty()) { // 中断命令执行 - this.interruptedTask(idList); + this.interruptTask(idList); // 删除执行日志 effect = execLogDAO.delete(wrapper); // 删除主机日志 @@ -256,9 +256,9 @@ public class ExecLogServiceImpl implements ExecLogService { // 中断执行 IExecTaskHandler task = execTaskManager.getTask(logId); if (task != null) { - log.info("ExecLogService.interruptExec interrupted logId: {}", logId); + log.info("ExecLogService.interruptExec interrupt logId: {}", logId); // 中断 - task.interrupted(); + task.interrupt(); } else { log.info("ExecLogService.interruptExec updateStatus start logId: {}", logId); // 不存在则直接修改状态 @@ -299,7 +299,7 @@ public class ExecLogServiceImpl implements ExecLogService { // 中断执行 IExecTaskHandler task = execTaskManager.getTask(logId); if (task != null) { - log.info("ExecLogService.interruptHostExec interrupted logId: {}, hostLogId: {}", logId, hostLogId); + log.info("ExecLogService.interruptHostExec interrupt logId: {}, hostLogId: {}", logId, hostLogId); IExecCommandHandler handler = task.getHandlers() .stream() .filter(s -> s.getHostId().equals(hostLog.getHostId())) @@ -307,7 +307,7 @@ public class ExecLogServiceImpl implements ExecLogService { .orElse(null); // 中断 if (handler != null) { - handler.interrupted(); + handler.interrupt(); } } else { log.info("ExecLogService.interruptHostExec updateStatus start logId: {}, hostLogId: {}", logId, hostLogId); @@ -465,11 +465,11 @@ public class ExecLogServiceImpl implements ExecLogService { * * @param idList idList */ - private void interruptedTask(List idList) { + private void interruptTask(List idList) { idList.stream() .map(execTaskManager::getTask) .filter(Objects::nonNull) - .forEach(IExecTaskHandler::interrupted); + .forEach(IExecTaskHandler::interrupt); } } diff --git a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/ExecLogFileAutoClearTask.java b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/ExecLogFileAutoClearTask.java index 04d3ef7c..b28ea9a9 100644 --- a/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/ExecLogFileAutoClearTask.java +++ b/orion-ops-module-asset/orion-ops-module-asset-service/src/main/java/com/orion/ops/module/asset/task/ExecLogFileAutoClearTask.java @@ -26,7 +26,7 @@ import java.util.List; */ @Slf4j @Component -@ConditionalOnProperty(value = "app.exec-log.auto-clear", havingValue = "true") +@ConditionalOnProperty(value = "app.exec-log.auto-clear", havingValue = "true", matchIfMissing = true) public class ExecLogFileAutoClearTask { /**