@@ -68,7 +65,7 @@
3. 账号可以开启 **MFA 两步验证**提高账号安全性
- 界面形式实时查看项目运行状态、控制台日志、管理项目文件
1. 在线修改项目文本文件
-- Docker 容器管理、Docker swarm 集群管理(**Docker ui**)
+- Docker 容器管理、Docker Swarm 集群管理(**Docker UI**)
- **在线 SSH 终端**,让您在没有 Xshell、FinalShell 等软件也能轻松管理服务器
1. 登录 Jpom 系统后不需要知道服务器密码
2. 能指定 SSH 禁止执行的命令,避免执行高风险命令,并且能自动执行命令日志
@@ -88,7 +85,7 @@
- 项目状态监控异常自动报警、自动尝试重启
1. 支持邮件 + 钉钉群 + 微信群通知,主动感知项目运行状况
- 节点脚本模版+定时执行或者触发器,拓展更多功能
-- 重要路径白名单模式,杜绝用户误操作系统文件
+- 重要路径授权配置,杜绝用户误操作系统文件
### 🔔️ 特别提醒
@@ -379,6 +376,26 @@ docker-compose -f docker-compose.yml up
2. 服务端示例:
[`logback.xml`](https://gitee.com/dromara/Jpom/blob/master/modules/server/src/main/resources/config_default/logback.xml)
+## 📝 常见问题、操作说明
+
+- [文档主页](https://jpom.top/)
+- [FQA](https://jpom.top/pages/FQA/)
+- [名词解释](https://jpom.top/pages/FQA/proper-noun/)
+
+### 实践案例
+
+> 里面有部分图片加载可能比较慢
+
+1. [本地构建 + SSH 发布 java 项目](https://jpom.top/pages/practice/build-java-ssh-release/)
+2. [本地构建 + 项目发布 node 项目](https://jpom.top/pages/practice/build-node-release/)
+3. [本地构建 + SSH 发布 node 项目](https://jpom.top/pages/practice/build-node-ssh-release/)
+4. [本地构建 + 自定义管理 python 项目](https://jpom.top/pages/practice/project-dsl-python/)
+5. [自定义管理 java 项目](https://jpom.top/pages/practice/project-dsl-java/)
+6. [管理编译安装的 nginx](https://jpom.top/pages/practice/node-nginx/)
+7. [管理 docker](https://jpom.top/pages/practice/docker-cli/)
+8. [容器构建 + 项目发布 java 项目](https://jpom.top/pages/practice/build-docker-java-node-release/)
+9. [更新实践案例>>](https://jpom.top/pages/practice/)
+
## 构建案例仓库代码
1. [Jboot 案例代码](https://gitee.com/keepbx/Jpom-demo-case/tree/master/jboot-test)
@@ -400,30 +417,37 @@ yarn --cwd xxxx/ build
mvn -f xxxx/pom.xml clean package
```
-## 📝 常见问题、操作说明
-
-- [文档主页](https://jpom.top/)
-- [FQA](https://jpom.top/pages/FQA/)
-- [名词解释](https://jpom.top/pages/FQA/proper-noun/)
-
-### 实践案例
-
-> 里面有部分图片加载可能比较慢
-
-1. [本地构建 + SSH 发布 java 项目](https://jpom.top/pages/practice/build-java-ssh-release/)
-2. [本地构建 + 项目发布 node 项目](https://jpom.top/pages/practice/build-node-release/)
-3. [本地构建 + SSH 发布 node 项目](https://jpom.top/pages/practice/build-node-ssh-release/)
-4. [本地构建 + 自定义管理 python 项目](https://jpom.top/pages/practice/project-dsl-python/)
-5. [自定义管理 java 项目](https://jpom.top/pages/practice/project-dsl-java/)
-6. [管理编译安装的 nginx](https://jpom.top/pages/practice/node-nginx/)
-7. [管理 docker](https://jpom.top/pages/practice/docker-cli/)
-8. [容器构建 + 项目发布 java 项目](https://jpom.top/pages/practice/build-docker-java-node-release/)
-9. [更新实践案例>>](https://jpom.top/pages/practice/)
-
## 🛠️ 整体架构
![jpom-func-arch](https://jpom.top/images/jpom-func-arch.png)
+
+## 🐞 交流讨论 、反馈 BUG、提出建议等
+
+1. 快扫描下方左侧微信群二维码和我们一起交流讨论吧!(添加小助手:备注 Jpom 进群)
+2. 开源项目离不开社区的支持,如果项目帮助到了你,并且想给我们加个餐。
+ 欢迎扫描下方[微信、支付宝收款码赞赏](https://jpom.top/images/praise-qrcorde.png)
+ 或通过[码云赞赏](https://gitee.com/dromara/Jpom)
+ (在项目首页下方点击捐赠,支持微信和支付宝)。[赞赏记录](https://jpom.top/pages/praise/publicity/)
+3. 购买开源周边商品:[周边介绍](https://jpom.top/pages/shop/)
+4. 企业技术服务请单独与我们联系沟通服务方案
+5. 反馈 BUG、提出建议,欢迎新建:[issues](https://gitee.com/dromara/Jpom/issues),开发人员会不定时查看回复。
+6. 参与贡献,请查看[贡献指南](#贡献指南)。
+
+感谢所有赞赏以及参与贡献的小伙伴,你们的支持是我们不断更新前进的动力!
+
+![wx-qrcode-praise.png](https://jpom.top/images/praise-qrcorde.png)
+
+## 💖 周边商品
+
+为了更好地维持开源项目,我们决定推出周边商品。
+
+购买支持我们这样您既获得了一份小商品我们也获得了您购买商品的利润(周边商品的价格会比市场价稍高,介意请勿下单)
+
+
+
+
+
## 🔨贡献指南
### 贡献须知
@@ -473,21 +497,6 @@ Jpom 作为开源项目,离不开社区的支持,欢迎任何人修改和提
> 目前用到的主要是 dev 和 docs 分支,接受 PR 修改,其他的分支为归档分支,贡献者可以不用管。
-## 🐞 交流讨论 、反馈 BUG、提出建议等
-
-1. 快扫描下方左侧微信群二维码和我们一起交流讨论吧!(添加小助手:备注 Jpom 进群)
-2. 开源项目离不开社区的支持,如果项目帮助到了你,并且想给我们加个餐。
- 欢迎扫描下方[微信、支付宝收款码赞赏](https://jpom.top/images/praise-qrcorde.png)
- 或通过[码云赞赏](https://gitee.com/dromara/Jpom)
- (在项目首页下方点击捐赠,支持微信和支付宝)。[赞赏记录](https://jpom.top/pages/praise/publicity/)
-3. 企业技术服务请单独与我们联系沟通服务方案
-4. 反馈 BUG、提出建议,欢迎新建:[issues](https://gitee.com/dromara/Jpom/issues),开发人员会不定时查看回复。
-5. 参与贡献,请查看[贡献指南](#贡献指南)。
-
-感谢所有赞赏以及参与贡献的小伙伴,你们的支持是我们不断更新前进的动力!
-
-![wx-qrcode-praise.png](https://jpom.top/images/praise-qrcorde.png)
-
## 🌍 知识星球
@@ -505,7 +514,7 @@ Jpom 作为开源项目,离不开社区的支持,欢迎任何人修改和提
| hippo4j | [https://gitee.com/magegoofy/hippo4j](https://gitee.com/magegoofy/hippo4j) | 强大的动态线程池框架,附带监控报警功能。 |
| HertzBeat | [https://gitee.com/dromara/hertzbeat](https://gitee.com/dromara/hertzbeat) | 易用友好的云监控系统, 无需 Agent, 强大自定义监控能力。 |
-## 鸣谢
+## 🤝 鸣谢
- 感谢 JetBrains 提供的免费开源 License:
diff --git a/SECURITY.md b/SECURITY.md
index 8330946a8..a2210d574 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -7,6 +7,7 @@ currently being supported with security updates.
| Version | Supported |
|-------------|--------------------|
+| 2.11.x | :white_check_mark: |
| 2.10.x | :white_check_mark: |
| 2.9.x | :white_check_mark: |
| 2.8.x | :x: |
diff --git a/env-beta.env b/env-beta.env
index 1d5ef59f6..90a06f2a4 100644
--- a/env-beta.env
+++ b/env-beta.env
@@ -1,3 +1,3 @@
-JPOM_VERSION=2.10.47.7
+JPOM_VERSION=2.11.0.8
# Server Token 生产部署请更换
SERVER_TOKEN=7094f673-2c53-4fc1-82e7-86e528449d97
diff --git a/modules/agent-transport/agent-transport-common/pom.xml b/modules/agent-transport/agent-transport-common/pom.xml
index 0de8bc99e..777fe4949 100644
--- a/modules/agent-transport/agent-transport-common/pom.xml
+++ b/modules/agent-transport/agent-transport-common/pom.xml
@@ -30,7 +30,7 @@
org.dromara.jpom.agent-transport
jpom-agent-transport-parent
- 2.10.47
+ 2.11.0.8
../pom.xml
diff --git a/modules/agent-transport/agent-transport-common/src/main/java/org/dromara/jpom/transport/AgentException.java b/modules/agent-transport/agent-transport-common/src/main/java/org/dromara/jpom/transport/TransportAgentException.java
similarity index 91%
rename from modules/agent-transport/agent-transport-common/src/main/java/org/dromara/jpom/transport/AgentException.java
rename to modules/agent-transport/agent-transport-common/src/main/java/org/dromara/jpom/transport/TransportAgentException.java
index 45a494596..277a58f2c 100644
--- a/modules/agent-transport/agent-transport-common/src/main/java/org/dromara/jpom/transport/AgentException.java
+++ b/modules/agent-transport/agent-transport-common/src/main/java/org/dromara/jpom/transport/TransportAgentException.java
@@ -29,9 +29,9 @@ import lombok.NoArgsConstructor;
* @since 2022/12/24
*/
@NoArgsConstructor
-public class AgentException extends RuntimeException {
+public class TransportAgentException extends RuntimeException {
- public AgentException(String message) {
+ public TransportAgentException(String message) {
super(message);
}
}
diff --git a/modules/agent-transport/agent-transport-http/pom.xml b/modules/agent-transport/agent-transport-http/pom.xml
index e08e3297c..dc151254c 100644
--- a/modules/agent-transport/agent-transport-http/pom.xml
+++ b/modules/agent-transport/agent-transport-http/pom.xml
@@ -30,7 +30,7 @@
org.dromara.jpom.agent-transport
jpom-agent-transport-parent
- 2.10.47
+ 2.11.0.8
../pom.xml
diff --git a/modules/agent-transport/agent-transport-http/src/main/java/org/dromara/jpom/transport/HttpTransportServer.java b/modules/agent-transport/agent-transport-http/src/main/java/org/dromara/jpom/transport/HttpTransportServer.java
index e5c1bf5e7..f168f09c1 100644
--- a/modules/agent-transport/agent-transport-http/src/main/java/org/dromara/jpom/transport/HttpTransportServer.java
+++ b/modules/agent-transport/agent-transport-http/src/main/java/org/dromara/jpom/transport/HttpTransportServer.java
@@ -108,7 +108,7 @@ public class HttpTransportServer implements TransportServer {
}
} catch (Exception e) {
log.error("编码异常", e);
- throw new AgentException("节点传输信息编码异常:" + e.getMessage());
+ throw new TransportAgentException("节点传输信息编码异常:" + e.getMessage());
}
});
}
@@ -124,7 +124,7 @@ public class HttpTransportServer implements TransportServer {
log.debug("Completed {}", body);
if (status != HttpStatus.HTTP_OK) {
log.warn("{} 响应异常 状态码错误:{} {}", nodeInfo.name(), status, body);
- throw new AgentException(nodeInfo.name() + " 节点响应异常,状态码错误:" + status);
+ throw new TransportAgentException(nodeInfo.name() + " 节点响应异常,状态码错误:" + status);
}
return body;
});
diff --git a/modules/agent-transport/pom.xml b/modules/agent-transport/pom.xml
index 397f78f73..e0654ee6b 100644
--- a/modules/agent-transport/pom.xml
+++ b/modules/agent-transport/pom.xml
@@ -29,7 +29,7 @@
jpom-parent
org.dromara.jpom
- 2.10.47
+ 2.11.0.8
../../pom.xml
pom
@@ -38,7 +38,7 @@
agent-transport-http
4.0.0
- 2.10.47
+ 2.11.0.8
org.dromara.jpom.agent-transport
jpom-agent-transport-parent
Jpom Agent Transport
diff --git a/modules/agent/pom.xml b/modules/agent/pom.xml
index fbf5dcc42..f6d11c5f0 100644
--- a/modules/agent/pom.xml
+++ b/modules/agent/pom.xml
@@ -29,12 +29,12 @@
jpom-parent
org.dromara.jpom
- 2.10.47
+ 2.11.0.8
../../pom.xml
4.0.0
agent
- 2.10.47
+ 2.11.0.8
Jpom Agent
org.dromara.jpom.JpomAgentApplication
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/AgentConst.java b/modules/agent/src/main/java/org/dromara/jpom/common/AgentConst.java
index c0f3b3d65..02fd6131d 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/AgentConst.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/AgentConst.java
@@ -30,7 +30,7 @@ package org.dromara.jpom.common;
*/
public class AgentConst {
/**
- * 白名单文件
+ * 授权文件
*/
public static final String WHITELIST_DIRECTORY = "whitelistDirectory.json";
/**
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/AgentExceptionHandler.java b/modules/agent/src/main/java/org/dromara/jpom/common/AgentExceptionHandler.java
index e88a47f5e..63034f91b 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/AgentExceptionHandler.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/AgentExceptionHandler.java
@@ -23,6 +23,7 @@
package org.dromara.jpom.common;
import lombok.extern.slf4j.Slf4j;
+import org.dromara.jpom.exception.BaseExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/BaseAgentController.java b/modules/agent/src/main/java/org/dromara/jpom/common/BaseAgentController.java
index 798ee2f80..e665eef8d 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/BaseAgentController.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/BaseAgentController.java
@@ -28,12 +28,12 @@ import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.servlet.ServletUtil;
import org.dromara.jpom.model.data.NodeProjectInfoModel;
import org.dromara.jpom.service.manage.ProjectInfoService;
+import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
-import java.util.Objects;
/**
* agent 端
@@ -42,6 +42,7 @@ import java.util.Objects;
* @since 2019/4/17
*/
public abstract class BaseAgentController extends BaseJpomController {
+
@Resource
protected ProjectInfoService projectInfoService;
@@ -83,8 +84,9 @@ public abstract class BaseAgentController extends BaseJpomController {
* @return NodeProjectInfoModel
*/
protected NodeProjectInfoModel getProjectInfoModel() {
- NodeProjectInfoModel nodeProjectInfoModel = tryGetProjectInfoModel();
- Objects.requireNonNull(nodeProjectInfoModel, "获取项目信息失败");
+ String id = getParameter("id");
+ NodeProjectInfoModel nodeProjectInfoModel = tryGetProjectInfoModel(id);
+ Assert.notNull(nodeProjectInfoModel, "获取项目信息失败:" + id);
return nodeProjectInfoModel;
}
@@ -95,7 +97,7 @@ public abstract class BaseAgentController extends BaseJpomController {
*/
protected NodeProjectInfoModel getProjectInfoModel(String id) {
NodeProjectInfoModel nodeProjectInfoModel = tryGetProjectInfoModel(id);
- Objects.requireNonNull(nodeProjectInfoModel, "获取项目信息失败");
+ Assert.notNull(nodeProjectInfoModel, "获取项目信息失败:" + id);
return nodeProjectInfoModel;
}
@@ -105,10 +107,9 @@ public abstract class BaseAgentController extends BaseJpomController {
}
protected NodeProjectInfoModel tryGetProjectInfoModel(String id) {
- NodeProjectInfoModel nodeProjectInfoModel = null;
if (StrUtil.isNotEmpty(id)) {
- nodeProjectInfoModel = projectInfoService.getItem(id);
+ return projectInfoService.getItem(id);
}
- return nodeProjectInfoModel;
+ return null;
}
}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/WebConfigurer.java b/modules/agent/src/main/java/org/dromara/jpom/common/WebConfigurer.java
index 14c4b4081..bdb3eb104 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/WebConfigurer.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/WebConfigurer.java
@@ -28,8 +28,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-import javax.annotation.Resource;
-
/**
* @author bwcx_jzy
* @since 2022/12/8
@@ -37,10 +35,14 @@ import javax.annotation.Resource;
@Configuration
public class WebConfigurer implements WebMvcConfigurer {
- @Resource
- private ParameterInterceptor parameterInterceptor;
- @Resource
- private AuthorizeInterceptor authorizeInterceptor;
+ private final ParameterInterceptor parameterInterceptor;
+ private final AuthorizeInterceptor authorizeInterceptor;
+
+ public WebConfigurer(ParameterInterceptor parameterInterceptor,
+ AuthorizeInterceptor authorizeInterceptor) {
+ this.parameterInterceptor = parameterInterceptor;
+ this.authorizeInterceptor = authorizeInterceptor;
+ }
@Override
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractProjectCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractProjectCommander.java
index 12c84bd01..36bb26cb6 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractProjectCommander.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractProjectCommander.java
@@ -35,31 +35,31 @@ import cn.hutool.core.map.SafeConcurrentHashMap;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
-import cn.hutool.extra.spring.SpringUtil;
-import cn.hutool.system.OsInfo;
import cn.hutool.system.SystemUtil;
import cn.keepbx.jpom.plugins.IPlugin;
import lombok.Lombok;
import lombok.extern.slf4j.Slf4j;
-import org.dromara.jpom.common.IllegalArgument2Exception;
-import org.dromara.jpom.common.commander.impl.LinuxProjectCommander;
-import org.dromara.jpom.common.commander.impl.MacOsProjectCommander;
-import org.dromara.jpom.common.commander.impl.WindowsProjectCommander;
+import org.dromara.jpom.exception.IllegalArgument2Exception;
+import org.dromara.jpom.configuration.ProjectConfig;
+import org.dromara.jpom.configuration.ProjectLogConfig;
import org.dromara.jpom.model.RunMode;
import org.dromara.jpom.model.data.DslYmlDto;
import org.dromara.jpom.model.data.NodeProjectInfoModel;
import org.dromara.jpom.model.system.NetstatModel;
import org.dromara.jpom.plugin.PluginFactory;
-import org.dromara.jpom.script.DslScriptBuilder;
+import org.dromara.jpom.service.manage.ProjectInfoService;
+import org.dromara.jpom.service.script.DslScriptServer;
import org.dromara.jpom.socket.AgentFileTailWatcher;
-import org.dromara.jpom.system.AgentConfig;
-import org.dromara.jpom.system.JpomRuntimeException;
+import org.dromara.jpom.socket.ConsoleCommandOp;
import org.dromara.jpom.util.CommandUtil;
import org.dromara.jpom.util.JvmUtil;
+import org.dromara.jpom.webhook.DefaultWebhookPluginImpl;
import org.springframework.util.Assert;
import java.io.File;
+import java.io.IOException;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.TimeUnit;
@@ -67,6 +67,7 @@ import java.util.function.BiFunction;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
+import java.util.stream.Collectors;
/**
* 项目命令执行基类
@@ -74,50 +75,39 @@ import java.util.jar.Manifest;
* @author Administrator
*/
@Slf4j
-public abstract class AbstractProjectCommander {
+public abstract class AbstractProjectCommander implements ProjectCommander {
public static final String RUNNING_TAG = "running";
public static final String STOP_TAG = "stopped";
private static final long BACK_LOG_MIN_SIZE = DataSizeUtil.parse("100KB");
- private static AbstractProjectCommander abstractProjectCommander = null;
+
/**
* 进程Id 获取端口号
*/
public static final Map> PID_PORT = new SafeConcurrentHashMap<>();
- private final Charset fileCharset;
+ protected final Charset fileCharset;
+ protected final SystemCommander systemCommander;
+ protected final ProjectConfig projectConfig;
+ protected final ProjectLogConfig projectLogConfig;
+ protected final DslScriptServer dslScriptServer;
+ protected final ProjectInfoService projectInfoService;
- public AbstractProjectCommander(Charset fileCharset) {
+ public AbstractProjectCommander(Charset fileCharset,
+ SystemCommander systemCommander,
+ ProjectConfig projectConfig,
+ DslScriptServer dslScriptServer,
+ ProjectInfoService projectInfoService) {
this.fileCharset = fileCharset;
+ this.systemCommander = systemCommander;
+ this.projectConfig = projectConfig;
+ this.projectLogConfig = projectConfig.getLog();
+ this.dslScriptServer = dslScriptServer;
+ this.projectInfoService = projectInfoService;
}
- /**
- * 实例化Commander
- *
- * @return 命令执行对象
- */
- public static AbstractProjectCommander getInstance() {
- if (abstractProjectCommander != null) {
- return abstractProjectCommander;
- }
- AgentConfig agentConfig = SpringUtil.getBean(AgentConfig.class);
- AgentConfig.ProjectConfig.LogConfig logConfig = agentConfig.getProject().getLog();
- OsInfo osInfo = SystemUtil.getOsInfo();
- if (osInfo.isLinux()) {
- // Linux系统
- abstractProjectCommander = new LinuxProjectCommander(logConfig.getFileCharset());
- } else if (osInfo.isWindows()) {
- // Windows系统
- abstractProjectCommander = new WindowsProjectCommander(logConfig.getFileCharset());
- } else if (osInfo.isMac()) {
- abstractProjectCommander = new MacOsProjectCommander(logConfig.getFileCharset());
- } else {
- throw new JpomRuntimeException("不支持的:" + osInfo.getName());
- }
- return abstractProjectCommander;
- }
//---------------------------------------------------- 基本操作----start
@@ -127,7 +117,15 @@ public abstract class AbstractProjectCommander {
* @param nodeProjectInfoModel 项目
* @return null 是条件不足
*/
- public abstract String buildJavaCommand(NodeProjectInfoModel nodeProjectInfoModel);
+ public abstract String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel);
+
+ /**
+ * 生成可以执行的命令
+ *
+ * @param nodeProjectInfoModel 项目
+ * @return null 是条件不足
+ */
+ public abstract String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel);
protected String getRunJavaPath(NodeProjectInfoModel nodeProjectInfoModel, boolean w) {
// if (StrUtil.isEmpty(nodeProjectInfoModel.getJdkId())) {
@@ -144,37 +142,25 @@ public abstract class AbstractProjectCommander {
// return jdkJavaPath;
}
- /**
- * 启动
- *
- * @param nodeProjectInfoModel 项目
- * @return 结果
- * @throws Exception 异常
- */
- public CommandOpResult start(NodeProjectInfoModel nodeProjectInfoModel) throws Exception {
- return this.start(nodeProjectInfoModel, false);
- }
-
/**
* 启动
*
* @param nodeProjectInfoModel 项目
* @param sync dsl 是否同步执行
* @return 结果
- * @throws Exception 异常
*/
- public CommandOpResult start(NodeProjectInfoModel nodeProjectInfoModel, boolean sync) throws Exception {
- String msg = checkStart(nodeProjectInfoModel);
+ protected CommandOpResult start(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, boolean sync) {
+ String msg = this.checkStart(nodeProjectInfoModel, originalModel);
if (msg != null) {
return CommandOpResult.of(false, msg);
}
- RunMode runMode = nodeProjectInfoModel.getRunMode();
+ RunMode runMode = originalModel.getRunMode();
if (runMode == RunMode.Dsl) {
//
- this.runDsl(nodeProjectInfoModel, "start", (baseProcess, action) -> {
- String log = nodeProjectInfoModel.getAbsoluteLog();
+ this.runDsl(originalModel, ConsoleCommandOp.start.name(), (baseProcess, action) -> {
+ String log = projectInfoService.resolveAbsoluteLog(nodeProjectInfoModel, originalModel);
try {
- DslScriptBuilder.run(baseProcess, nodeProjectInfoModel, action, log, sync);
+ dslScriptServer.run(baseProcess, nodeProjectInfoModel, originalModel, action, log, sync);
} catch (Exception e) {
throw Lombok.sneakyThrow(e);
}
@@ -182,18 +168,18 @@ public abstract class AbstractProjectCommander {
});
} else {
- String command = this.buildJavaCommand(nodeProjectInfoModel);
+ String command = this.buildRunCommand(nodeProjectInfoModel, originalModel);
if (command == null) {
return CommandOpResult.of(false, "没有需要执行的命令");
}
// 执行命令
ThreadUtil.execute(() -> {
try {
- File file = FileUtil.file(nodeProjectInfoModel.allLib());
+ File file = projectInfoService.resolveLibFile(nodeProjectInfoModel);
if (SystemUtil.getOsInfo().isWindows()) {
CommandUtil.execSystemCommand(command, file);
} else {
- CommandUtil.asyncExeLocalCommand(file, command);
+ CommandUtil.asyncExeLocalCommand(command, file);
}
} catch (Exception e) {
log.error("执行命令失败", e);
@@ -201,9 +187,9 @@ public abstract class AbstractProjectCommander {
});
}
//
- this.loopCheckRun(nodeProjectInfoModel, true);
- CommandOpResult status = this.status(nodeProjectInfoModel);
- this.asyncWebHooks(nodeProjectInfoModel, "start", "result", status.msgStr());
+ this.loopCheckRun(nodeProjectInfoModel, originalModel, true);
+ CommandOpResult status = this.status(nodeProjectInfoModel, originalModel);
+ this.asyncWebHooks(nodeProjectInfoModel, originalModel, "start", "result", status.msgStr());
return status;
}
@@ -219,18 +205,8 @@ public abstract class AbstractProjectCommander {
* @param listening 是否只获取检查状态的
* @return 数组
*/
- public abstract List listNetstat(int pid, boolean listening);
+ protected abstract List listNetstat(int pid, boolean listening);
- /**
- * 停止
- *
- * @param nodeProjectInfoModel 项目
- * @return 结果
- * @throws Exception 异常
- */
- public CommandOpResult stop(NodeProjectInfoModel nodeProjectInfoModel) throws Exception {
- return this.stop(nodeProjectInfoModel, false);
- }
/**
* 停止
@@ -238,39 +214,41 @@ public abstract class AbstractProjectCommander {
* @param nodeProjectInfoModel 项目
* @param sync dsl 是否同步执行
* @return 结果
- * @throws Exception 异常
*/
- public CommandOpResult stop(NodeProjectInfoModel nodeProjectInfoModel, boolean sync) throws Exception {
+ protected CommandOpResult stop(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, boolean sync) {
RunMode runMode = nodeProjectInfoModel.getRunMode();
if (runMode == RunMode.File) {
return CommandOpResult.of(true, "file 类型项目没有 stop");
}
- Tuple tuple = this.stopBefore(nodeProjectInfoModel);
+
+ Tuple tuple = this.stopBefore(nodeProjectInfoModel, originalModel);
CommandOpResult status = tuple.get(1);
String webHook = tuple.get(0);
if (status.isSuccess()) {
// 运行中
if (runMode == RunMode.Dsl) {
//
- this.runDsl(nodeProjectInfoModel, "stop", (process, action) -> {
- String log = nodeProjectInfoModel.getAbsoluteLog();
+ this.runDsl(originalModel, ConsoleCommandOp.stop.name(), (process, action) -> {
+ String log = projectInfoService.resolveAbsoluteLog(nodeProjectInfoModel, originalModel);
try {
- DslScriptBuilder.run(process, nodeProjectInfoModel, action, log, sync);
+ dslScriptServer.run(process, nodeProjectInfoModel, originalModel, action, log, sync);
} catch (Exception e) {
throw Lombok.sneakyThrow(e);
}
return null;
});
- boolean checkRun = this.loopCheckRun(nodeProjectInfoModel, false);
+ boolean checkRun = this.loopCheckRun(nodeProjectInfoModel, originalModel, false);
return CommandOpResult.of(checkRun, checkRun ? "stop done" : "stop done,but unsuccessful")
.appendMsg(status.getMsgs())
.appendMsg(webHook);
} else {
//
- return this.stopJava(nodeProjectInfoModel, status.getPid()).appendMsg(status.getMsgs()).appendMsg(webHook);
+ return this.stopJava(nodeProjectInfoModel, originalModel, status.getPid()).appendMsg(status.getMsgs()).appendMsg(webHook);
}
}
- return CommandOpResult.of(true).appendMsg(status.getMsgs()).appendMsg(webHook);
+ return CommandOpResult.of(true).
+ appendMsg(status.getMsgs()).
+ appendMsg(webHook);
}
/**
@@ -279,26 +257,24 @@ public abstract class AbstractProjectCommander {
* @param nodeProjectInfoModel 项目
* @param pid 进程ID
* @return 结果
- * @throws Exception 异常
*/
- public abstract CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, int pid) throws Exception;
+ protected abstract CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, int pid);
/**
* 停止之前
*
* @param nodeProjectInfoModel 项目
* @return 结果
- * @throws Exception 异常
*/
- private Tuple stopBefore(NodeProjectInfoModel nodeProjectInfoModel) throws Exception {
- String beforeStop = this.webHooks(nodeProjectInfoModel, "beforeStop");
+ private Tuple stopBefore(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
+ String beforeStop = this.webHooks(nodeProjectInfoModel.token(), nodeProjectInfoModel, "beforeStop");
// 再次查看进程信息
- CommandOpResult result = this.status(nodeProjectInfoModel);
+ CommandOpResult result = this.status(nodeProjectInfoModel, originalModel);
if (result.isSuccess()) {
// 端口号缓存
PID_PORT.remove(result.getPid());
}
- this.asyncWebHooks(nodeProjectInfoModel, "stop", "result", result);
+ this.asyncWebHooks(nodeProjectInfoModel, originalModel, "stop", "result", result);
return new Tuple(StrUtil.emptyToDefault(beforeStop, StrUtil.EMPTY), result);
}
@@ -312,17 +288,54 @@ public abstract class AbstractProjectCommander {
public void asyncWebHooks(NodeProjectInfoModel nodeProjectInfoModel,
String type, Object... other) {
- String token = nodeProjectInfoModel.getToken();
- Opt.ofBlankAble(token)
+ NodeProjectInfoModel infoModel = projectInfoService.resolveModel(nodeProjectInfoModel);
+ this.asyncWebHooks(nodeProjectInfoModel, infoModel, type, other);
+ }
+
+ /**
+ * 执行 webhooks 通知
+ *
+ * @param nodeProjectInfoModel 项目信息
+ * @param type 类型
+ * @param other 其他参数
+ */
+ public void asyncWebHooks(NodeProjectInfoModel nodeProjectInfoModel,
+ NodeProjectInfoModel originalModel,
+ String type, Object... other) {
+ // webhook 通知
+ Opt.ofBlankAble(nodeProjectInfoModel.token())
.ifPresent(s ->
ThreadUtil.execute(() -> {
try {
- this.webHooks(nodeProjectInfoModel, type, other);
+ String result = this.webHooks(s, nodeProjectInfoModel, type, other);
+ Optional.ofNullable(result).ifPresent(s1 -> log.debug("[{}]-{}触发器结果:{}", nodeProjectInfoModel.getId(), type, s1));
} catch (Exception e) {
log.error("project webhook", e);
}
})
);
+ // 判断文件变动
+ if (StrUtil.equals(type, "fileChange")) {
+ RunMode runMode = originalModel.getRunMode();
+ if (runMode == RunMode.Dsl) {
+ DslYmlDto dslYmlDto = originalModel.mustDslConfig();
+ if (dslYmlDto.hasRunProcess(ConsoleCommandOp.reload.name())) {
+ DslYmlDto.Run run = dslYmlDto.getRun();
+ Boolean fileChangeReload = run.getFileChangeReload();
+ if (fileChangeReload != null && fileChangeReload) {
+ // 需要执行重载事件
+ ThreadUtil.execute(() -> {
+ try {
+ CommandOpResult reload = this.reload(nodeProjectInfoModel, originalModel);
+ log.info("触发项目 reload 事件:{}", reload);
+ } catch (Exception e) {
+ log.error("重载项目异常", e);
+ }
+ });
+ }
+ }
+ }
+ }
}
/**
@@ -333,21 +346,26 @@ public abstract class AbstractProjectCommander {
* @param other 其他参数
* @return 结果
*/
- private String webHooks(NodeProjectInfoModel nodeProjectInfoModel,
-
- String type, Object... other) throws Exception {
- String token = nodeProjectInfoModel.getToken();
+ private String webHooks(String token, NodeProjectInfoModel nodeProjectInfoModel, String type, Object... other) {
+ if (StrUtil.isEmpty(token)) {
+ return null;
+ }
IPlugin plugin = PluginFactory.getPlugin("webhook");
Map map = new HashMap<>(10);
map.put("projectId", nodeProjectInfoModel.getId());
map.put("projectName", nodeProjectInfoModel.getName());
map.put("type", type);
+ map.put("JPOM_WEBHOOK_EVENT", DefaultWebhookPluginImpl.WebhookEvent.PROJECT);
for (int i = 0; i < other.length; i += 2) {
map.put(other[i].toString(), other[i + 1]);
}
- Object execute = plugin.execute(token, map);
- return Convert.toStr(execute, StrUtil.EMPTY);
+ try {
+ Object execute = plugin.execute(token, map);
+ return Convert.toStr(execute, StrUtil.EMPTY);
+ } catch (Exception e) {
+ throw Lombok.sneakyThrow(e);
+ }
}
/**
@@ -355,40 +373,42 @@ public abstract class AbstractProjectCommander {
*
* @param nodeProjectInfoModel 项目
* @return 结果
- * @throws Exception 异常
*/
- public CommandOpResult restart(NodeProjectInfoModel nodeProjectInfoModel) throws Exception {
- RunMode runMode = nodeProjectInfoModel.getRunMode();
+ protected CommandOpResult restart(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
+ RunMode runMode = originalModel.getRunMode();
if (runMode == RunMode.File) {
return CommandOpResult.of(true, "file 类型项目没有 restart");
}
- this.asyncWebHooks(nodeProjectInfoModel, "beforeRestart");
+ this.asyncWebHooks(nodeProjectInfoModel, originalModel, "beforeRestart");
if (runMode == RunMode.Dsl) {
- DslYmlDto.BaseProcess dslProcess = nodeProjectInfoModel.tryDslProcess("restart");
+ DslYmlDto.BaseProcess dslProcess = originalModel.tryDslProcess(ConsoleCommandOp.restart.name());
if (dslProcess != null) {
+ // 如果存在自定义 restart 流程
//
- this.runDsl(nodeProjectInfoModel, "restart", (process, action) -> {
- String log = nodeProjectInfoModel.getAbsoluteLog();
+ this.runDsl(originalModel, ConsoleCommandOp.restart.name(), (process, action) -> {
+ String log = projectInfoService.resolveAbsoluteLog(nodeProjectInfoModel, originalModel);
try {
- DslScriptBuilder.run(process, nodeProjectInfoModel, action, log, false);
+ dslScriptServer.run(process, nodeProjectInfoModel, originalModel, action, log, false);
} catch (Exception e) {
throw Lombok.sneakyThrow(e);
}
return null;
});
// 等待 状态成功
- boolean run = this.loopCheckRun(nodeProjectInfoModel, true);
- return CommandOpResult.of(run, run ? "restart done" : "restart done,but unsuccessful");
+ boolean run = this.loopCheckRun(nodeProjectInfoModel, originalModel, true);
+ CommandOpResult result = CommandOpResult.of(run, run ? "restart done" : "restart done,but unsuccessful");
+ this.asyncWebHooks(nodeProjectInfoModel, originalModel, "restart", "result", result);
+ return result;
//return new Tuple(run ? "restart done,but unsuccessful" : "restart done", resultMsg);
}
}
- boolean run = this.isRun(nodeProjectInfoModel);
+ boolean run = this.isRun(nodeProjectInfoModel, originalModel);
CommandOpResult stopMsg = null;
if (run) {
- stopMsg = this.stop(nodeProjectInfoModel, true);
+ stopMsg = this.stop(nodeProjectInfoModel, originalModel, true);
}
- CommandOpResult startMsg = this.start(nodeProjectInfoModel);
+ CommandOpResult startMsg = this.start(nodeProjectInfoModel, originalModel, false);
if (stopMsg != null) {
startMsg.appendMsg(stopMsg.getMsgs());
}
@@ -400,35 +420,38 @@ public abstract class AbstractProjectCommander {
*
* @param nodeProjectInfoModel 项目
* @return null 检查一切正常
- * @throws Exception 异常
*/
- private String checkStart(NodeProjectInfoModel nodeProjectInfoModel) throws Exception {
- CommandOpResult status = this.status(nodeProjectInfoModel);
+ private String checkStart(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
+ CommandOpResult status = this.status(nodeProjectInfoModel, originalModel);
if (status.isSuccess()) {
return "当前程序正在运行中,不能重复启动,PID:" + status.getPid();
}
- String lib = nodeProjectInfoModel.allLib();
- File fileLib = new File(lib);
+ File fileLib = projectInfoService.resolveLibFile(nodeProjectInfoModel);
File[] files = fileLib.listFiles();
if (files == null || files.length == 0) {
return "项目目录没有任何文件,请先到项目文件管理中上传文件";
}
//
- RunMode runMode = nodeProjectInfoModel.getRunMode();
- if (runMode == RunMode.Dsl) {
+
+ RunMode checkRunMode = originalModel.getRunMode();
+ if (checkRunMode == RunMode.Dsl) {
//
- String dslContent = nodeProjectInfoModel.getDslContent();
- } else if (runMode == RunMode.ClassPath || runMode == RunMode.JavaExtDirsCp) {
+ originalModel.mustDslConfig();
+ } else if (checkRunMode == RunMode.ClassPath || checkRunMode == RunMode.JavaExtDirsCp) {
// 判断主类
+ String mainClass = originalModel.mainClass();
try (JarClassLoader jarClassLoader = JarClassLoader.load(fileLib)) {
- jarClassLoader.loadClass(nodeProjectInfoModel.getMainClass());
+ jarClassLoader.loadClass(mainClass);
} catch (ClassNotFoundException notFound) {
- return "没有找到对应的MainClass:" + nodeProjectInfoModel.getMainClass();
+ return "没有找到对应的MainClass:" + mainClass;
+ } catch (IOException io) {
+ throw Lombok.sneakyThrow(io);
}
- } else if (runMode == RunMode.Jar || runMode == RunMode.JarWar) {
- List fileList = NodeProjectInfoModel.listJars(nodeProjectInfoModel);
+ } else if (checkRunMode == RunMode.Jar || checkRunMode == RunMode.JarWar) {
+
+ List fileList = this.listJars(checkRunMode, fileLib);
if (fileList.isEmpty()) {
- return String.format("一级目录没有%s包,请先到文件管理中上传程序的%s", runMode.name(), runMode.name());
+ return String.format("一级目录没有%s包,请先到文件管理中上传程序的%s", checkRunMode.name(), checkRunMode.name());
}
File jarFile = fileList.get(0);
String checkJar = checkJar(jarFile);
@@ -439,10 +462,16 @@ public abstract class AbstractProjectCommander {
return "当前项目类型不支持启动";
}
// 备份日志
- backLog(nodeProjectInfoModel);
+ this.backLog(nodeProjectInfoModel, originalModel);
return null;
}
+ /**
+ * 校验jar包
+ *
+ * @param jarFile jar 文件
+ * @return mainClass
+ */
private static String checkJar(File jarFile) {
try (JarFile jarFile1 = new JarFile(jarFile)) {
Manifest manifest = jarFile1.getManifest();
@@ -469,13 +498,11 @@ public abstract class AbstractProjectCommander {
* @param nodeProjectInfoModel 项目实体
* @return true 开启日志备份
*/
- private boolean resolveOpenLogBack(NodeProjectInfoModel nodeProjectInfoModel) {
- RunMode runMode = nodeProjectInfoModel.getRunMode();
- AgentConfig agentConfig = SpringUtil.getBean(AgentConfig.class);
- boolean autoBackToFile = agentConfig.getProject().getLog().isAutoBackupToFile();
+ private boolean resolveOpenLogBack(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
+ RunMode runMode = originalModel.getRunMode();
+ boolean autoBackToFile = projectLogConfig.isAutoBackupToFile();
if (runMode == RunMode.Dsl) {
- DslYmlDto dslYmlDto = nodeProjectInfoModel.dslConfig();
- return Optional.ofNullable(dslYmlDto)
+ return Optional.ofNullable(originalModel.dslConfig())
.map(DslYmlDto::getConfig)
.map(DslYmlDto.Config::getAutoBackToFile)
.orElse(autoBackToFile);
@@ -490,7 +517,18 @@ public abstract class AbstractProjectCommander {
* @return 结果
*/
public String backLog(NodeProjectInfoModel nodeProjectInfoModel) {
- File file = new File(nodeProjectInfoModel.getLog());
+ NodeProjectInfoModel infoModel = projectInfoService.resolveModel(nodeProjectInfoModel);
+ return this.backLog(nodeProjectInfoModel, infoModel);
+ }
+
+ /**
+ * 清空日志信息
+ *
+ * @param nodeProjectInfoModel 项目
+ * @return 结果
+ */
+ public String backLog(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
+ File file = projectInfoService.resolveAbsoluteLogFile(nodeProjectInfoModel, originalModel);
if (!file.exists() || file.isDirectory()) {
return "not exists";
}
@@ -499,15 +537,16 @@ public abstract class AbstractProjectCommander {
if (file.length() <= BACK_LOG_MIN_SIZE) {
return "ok";
}
- boolean openLogBack = this.resolveOpenLogBack(nodeProjectInfoModel);
+ boolean openLogBack = this.resolveOpenLogBack(nodeProjectInfoModel, originalModel);
if (openLogBack) {
// 开启日志备份才移动文件
- File backPath = nodeProjectInfoModel.getLogBack();
- backPath = new File(backPath, DateTime.now().toString(DatePattern.PURE_DATETIME_FORMAT) + ".log");
+ File backPath = projectInfoService.resolveLogBack(nodeProjectInfoModel, originalModel);
+ String pathId = DateTime.now().toString(DatePattern.PURE_DATETIME_FORMAT) + ".log";
+ backPath = new File(backPath, pathId);
FileUtil.copy(file, backPath, true);
}
// 清空日志
- String r = AbstractSystemCommander.getInstance().emptyLogFile(file);
+ String r = systemCommander.emptyLogFile(file);
if (StrUtil.isNotEmpty(r)) {
log.info(r);
}
@@ -522,16 +561,28 @@ public abstract class AbstractProjectCommander {
* @param nodeProjectInfoModel 项目
* @return 状态
*/
- public CommandOpResult status(NodeProjectInfoModel nodeProjectInfoModel) {
- RunMode runMode = nodeProjectInfoModel.getRunMode();
+ protected CommandOpResult status(NodeProjectInfoModel nodeProjectInfoModel) {
+ NodeProjectInfoModel originalModel = projectInfoService.resolveModel(nodeProjectInfoModel);
+ return this.status(nodeProjectInfoModel, originalModel);
+ }
+
+ /**
+ * 查询项目状态
+ *
+ * @param nodeProjectInfoModel 项目
+ * @return 状态
+ */
+ protected CommandOpResult status(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
+ RunMode runMode = originalModel.getRunMode();
if (runMode == RunMode.File) {
return CommandOpResult.of(false, "file 类型项目没有运行状态");
}
if (runMode == RunMode.Dsl) {
- List status = this.runDsl(nodeProjectInfoModel, "status", (baseProcess, action) -> {
+ List status = this.runDsl(originalModel, ConsoleCommandOp.status.name(), (baseProcess, action) -> {
// 提前判断脚本 id,避免填写错误在删除项目检测状态时候异常
try {
- return DslScriptBuilder.syncRun(baseProcess, nodeProjectInfoModel, action);
+ Tuple tuple = dslScriptServer.syncRun(baseProcess, nodeProjectInfoModel, originalModel, action);
+ return tuple.get(1);
} catch (IllegalArgument2Exception argument2Exception) {
log.warn("执行 DSL 脚本异常:{}", argument2Exception.getMessage());
return CollUtil.newArrayList(argument2Exception.getMessage());
@@ -540,8 +591,8 @@ public abstract class AbstractProjectCommander {
return Optional.ofNullable(status)
.map(strings -> {
- String log = nodeProjectInfoModel.getAbsoluteLog();
- FileUtil.appendLines(strings, FileUtil.file(log), fileCharset);
+ File log = projectInfoService.resolveAbsoluteLogFile(nodeProjectInfoModel, originalModel);
+ FileUtil.appendLines(strings, log, fileCharset);
return strings;
})
.map(CollUtil::getLast)
@@ -562,6 +613,36 @@ public abstract class AbstractProjectCommander {
}
}
+ /**
+ * 重新加载
+ *
+ * @param nodeProjectInfoModel 项目
+ * @return 结果
+ */
+ protected CommandOpResult reload(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
+ RunMode runMode = originalModel.getRunMode();
+ Assert.state(runMode == RunMode.Dsl, "非 DSL 项目不支持此操作");
+ CommandOpResult commandOpResult = this.runDsl(originalModel, ConsoleCommandOp.reload.name(), (baseProcess, action) -> {
+ // 提前判断脚本 id,避免填写错误在删除项目检测状态时候异常
+ try {
+ Tuple tuple = dslScriptServer.syncRun(baseProcess, nodeProjectInfoModel, originalModel, action);
+ int code = tuple.get(0);
+ List list = tuple.get(1);
+ // 如果退出码为 0 认为执行成功
+ return CommandOpResult.of(code == 0, list);
+ } catch (IllegalArgument2Exception argument2Exception) {
+ log.warn("执行 DSL 脚本异常:{}", argument2Exception.getMessage());
+ return CommandOpResult.of(false, argument2Exception.getMessage());
+ }
+ });
+ // 缓存执行结果
+ NodeProjectInfoModel update = new NodeProjectInfoModel();
+ update.setLastReloadResult(commandOpResult);
+ projectInfoService.updateById(update, nodeProjectInfoModel.getId());
+ this.asyncWebHooks(nodeProjectInfoModel, originalModel, "reload", "result", commandOpResult);
+ return commandOpResult;
+ }
+
/**
* 查看状态
*
@@ -570,12 +651,23 @@ public abstract class AbstractProjectCommander {
*/
protected String status(String tag) {
String jpsStatus = this.getJpsStatus(tag);
- if (StrUtil.equals(AbstractProjectCommander.STOP_TAG, jpsStatus) && SystemUtil.getOsInfo().isLinux()) {
- return getLinuxPsStatus(tag);
+ if (StrUtil.equals(AbstractProjectCommander.STOP_TAG, jpsStatus)) {
+ // 通过系统命令查询
+ return this.bySystemPs(tag);
}
return jpsStatus;
}
+ /**
+ * 通过系统命令查询进程是否存在
+ *
+ * @param tag 进程标识
+ * @return 是否存在
+ */
+ protected String bySystemPs(String tag) {
+ return AbstractProjectCommander.STOP_TAG;
+ }
+
/**
* 尝试jps 中查看进程id
*
@@ -590,27 +682,7 @@ public abstract class AbstractProjectCommander {
return StrUtil.format("{}:{}", AbstractProjectCommander.RUNNING_TAG, pid);
}
-
- /**
- * 尝试ps -ef | grep 中查看进程id
- *
- * @param tag 进程标识
- * @return 运行标识
- */
- private String getLinuxPsStatus(String tag) {
- String execSystemCommand = CommandUtil.execSystemCommand("ps -ef | grep " + tag);
- log.debug("getLinuxPsStatus {} {}", tag, execSystemCommand);
- List list = StrSplitter.splitTrim(execSystemCommand, StrUtil.LF, true);
- for (String item : list) {
- if (JvmUtil.checkCommandLineIsJpom(item, tag)) {
- String[] split = StrUtil.splitToArray(item, StrUtil.SPACE);
- return StrUtil.format("{}:{}", AbstractProjectCommander.RUNNING_TAG, split[1]);
- }
- }
- return AbstractProjectCommander.STOP_TAG;
- }
-
- //---------------------------------------------------- 基本操作----end
+//---------------------------------------------------- 基本操作----end
/**
* 获取进程占用的主要端口
@@ -618,15 +690,15 @@ public abstract class AbstractProjectCommander {
* @param pid 进程id
* @return 端口
*/
- public String getMainPort(int pid) {
- if (pid <= 0) {
+ public String getMainPort(Integer pid) {
+ if (pid == null || pid <= 0) {
return StrUtil.DASHED;
}
String cachePort = CacheObject.get(PID_PORT, pid);
if (cachePort != null) {
return cachePort;
}
- List list = listNetstat(pid, true);
+ List list = this.listNetstat(pid, true);
if (list == null) {
return StrUtil.DASHED;
}
@@ -683,7 +755,18 @@ public abstract class AbstractProjectCommander {
* @return true 正在运行
*/
public boolean isRun(NodeProjectInfoModel nodeProjectInfoModel) {
- CommandOpResult result = this.status(nodeProjectInfoModel);
+ NodeProjectInfoModel originalModel = projectInfoService.resolveModel(nodeProjectInfoModel);
+ return this.isRun(nodeProjectInfoModel, originalModel);
+ }
+
+ /**
+ * 是否正在运行
+ *
+ * @param nodeProjectInfoModel 项目
+ * @return true 正在运行
+ */
+ public boolean isRun(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
+ CommandOpResult result = this.status(nodeProjectInfoModel, originalModel);
return result.isSuccess();
}
@@ -694,9 +777,9 @@ public abstract class AbstractProjectCommander {
*
* @return 和参数status相反
*/
- protected boolean loopCheckRun(NodeProjectInfoModel nodeProjectInfoModel, boolean status) {
- int statusWaitTime = AgentConfig.ProjectConfig.getInstance().getStatusWaitTime();
- return this.loopCheckRun(nodeProjectInfoModel, statusWaitTime, status);
+ protected boolean loopCheckRun(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, boolean status) {
+ int statusWaitTime = projectConfig.getStatusWaitTime();
+ return this.loopCheckRun(nodeProjectInfoModel, originalModel, statusWaitTime, status);
}
/***
@@ -707,14 +790,14 @@ public abstract class AbstractProjectCommander {
*
* @return 如果和期望一致则返回 true,反之 false
*/
- protected boolean loopCheckRun(NodeProjectInfoModel nodeProjectInfoModel, int waitTime, boolean status) {
+ protected boolean loopCheckRun(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, int waitTime, boolean status) {
waitTime = Math.max(waitTime, 1);
- int statusDetectionInterval = AgentConfig.ProjectConfig.getInstance().getStatusDetectionInterval();
+ int statusDetectionInterval = projectConfig.getStatusDetectionInterval();
statusDetectionInterval = Math.max(statusDetectionInterval, 1);
int loopCount = (int) (TimeUnit.SECONDS.toMillis(waitTime) / 500);
int count = 0;
do {
- if (this.isRun(nodeProjectInfoModel) == status) {
+ if (this.isRun(nodeProjectInfoModel, originalModel) == status) {
// 是期望的结果
return true;
}
@@ -722,4 +805,124 @@ public abstract class AbstractProjectCommander {
} while (count++ < loopCount);
return false;
}
+
+ /**
+ * 执行shell命令
+ *
+ * @param consoleCommandOp 执行的操作
+ * @param nodeProjectInfoModel 项目信息
+ * @return 执行结果
+ */
+ public CommandOpResult execCommand(ConsoleCommandOp consoleCommandOp, NodeProjectInfoModel nodeProjectInfoModel) {
+ NodeProjectInfoModel originalModel = projectInfoService.resolveModel(nodeProjectInfoModel);
+ CommandOpResult result;
+ // 执行命令
+ switch (consoleCommandOp) {
+ case restart:
+ result = this.restart(nodeProjectInfoModel, originalModel);
+ break;
+ case start:
+ result = this.start(nodeProjectInfoModel, originalModel, false);
+ break;
+ case stop:
+ result = this.stop(nodeProjectInfoModel, originalModel, false);
+ break;
+ case status: {
+ result = this.status(nodeProjectInfoModel, originalModel);
+ break;
+ }
+ case reload: {
+ result = this.reload(nodeProjectInfoModel, originalModel);
+ break;
+ }
+ case showlog:
+ default:
+ throw new IllegalArgumentException(consoleCommandOp + " error");
+ }
+ return result;
+ }
+
+ /**
+ * 获取项目文件中的所有jar 文件
+ *
+ * @param runMode 运行模式
+ * @param path 目录
+ * @return list
+ */
+ protected List listJars(RunMode runMode, String path) {
+ //File fileLib = projectInfoService.resolveLibFile(nodeProjectInfoModel);
+ return this.listJars(runMode, FileUtil.file(path));
+ }
+
+ /**
+ * 获取项目文件中的所有jar 文件
+ *
+ * @param runMode 运行模式
+ * @param path 目录
+ * @return list
+ */
+ protected List listJars(RunMode runMode, File path) {
+ File[] files = path.listFiles();
+ if (files == null) {
+ return new ArrayList<>();
+ }
+ return Arrays.stream(files)
+ .filter(File::isFile)
+ .filter(file -> {
+ if (runMode == RunMode.ClassPath || runMode == RunMode.Jar || runMode == RunMode.JavaExtDirsCp) {
+ return StrUtil.endWith(file.getName(), FileUtil.JAR_FILE_EXT, true);
+ } else if (runMode == RunMode.JarWar) {
+ return StrUtil.endWith(file.getName(), "war", true);
+ }
+ return false;
+ })
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * 拼接java 执行的jar路径
+ *
+ * @param nodeProjectInfoModel 项目
+ * @return classpath 或者 jar
+ */
+ protected String getClassPathLib(NodeProjectInfoModel nodeProjectInfoModel, String lib) {
+ RunMode runMode = nodeProjectInfoModel.getRunMode();
+ List files = this.listJars(runMode, lib);
+ if (CollUtil.isEmpty(files)) {
+ return "";
+ }
+ // 获取lib下面的所有jar包
+ StringBuilder classPath = new StringBuilder();
+
+ int len = files.size();
+ if (runMode == RunMode.ClassPath) {
+ classPath.append("-classpath ");
+ } else if (runMode == RunMode.Jar || runMode == RunMode.JarWar) {
+ classPath.append("-jar ");
+ // 只取一个jar文件
+ len = 1;
+ } else if (runMode == RunMode.JavaExtDirsCp) {
+ classPath.append("-Djava.ext.dirs=");
+ String javaExtDirsCp = nodeProjectInfoModel.javaExtDirsCp();
+ String[] split = StrUtil.splitToArray(javaExtDirsCp, StrUtil.COLON);
+ if (ArrayUtil.isEmpty(split)) {
+ classPath.append(". -cp ");
+ } else {
+ classPath.append(split[0]).append(" -cp ");
+ if (split.length > 1) {
+ classPath.append(split[1]).append(FileUtil.PATH_SEPARATOR);
+ }
+ }
+ } else {
+ return StrUtil.EMPTY;
+ }
+ for (int i = 0; i < len; i++) {
+ File file = files.get(i);
+ classPath.append(file.getAbsolutePath());
+ if (i != len - 1) {
+ classPath.append(FileUtil.PATH_SEPARATOR);
+ }
+ }
+ return classPath.toString();
+ }
}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractSystemCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractSystemCommander.java
index 618e25d0b..b2706c233 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractSystemCommander.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/AbstractSystemCommander.java
@@ -22,11 +22,6 @@
*/
package org.dromara.jpom.common.commander;
-import cn.hutool.system.SystemUtil;
-import org.dromara.jpom.common.commander.impl.LinuxSystemCommander;
-import org.dromara.jpom.common.commander.impl.MacOsSystemCommander;
-import org.dromara.jpom.common.commander.impl.WindowsSystemCommander;
-import org.dromara.jpom.system.JpomRuntimeException;
import org.dromara.jpom.util.CommandUtil;
import java.io.File;
@@ -37,27 +32,8 @@ import java.io.File;
* @author bwcx_jzy
* @since 2019/4/16
*/
-public abstract class AbstractSystemCommander {
+public abstract class AbstractSystemCommander implements SystemCommander {
- private static AbstractSystemCommander abstractSystemCommander = null;
-
- public static AbstractSystemCommander getInstance() {
- if (abstractSystemCommander != null) {
- return abstractSystemCommander;
- }
- if (SystemUtil.getOsInfo().isLinux()) {
- // Linux系统
- abstractSystemCommander = new LinuxSystemCommander();
- } else if (SystemUtil.getOsInfo().isWindows()) {
- // Windows系统
- abstractSystemCommander = new WindowsSystemCommander();
- } else if (SystemUtil.getOsInfo().isMac()) {
- abstractSystemCommander = new MacOsSystemCommander();
- } else {
- throw new JpomRuntimeException("不支持的:" + SystemUtil.getOsInfo().getName());
- }
- return abstractSystemCommander;
- }
/**
* 清空文件内容
@@ -67,29 +43,29 @@ public abstract class AbstractSystemCommander {
*/
public abstract String emptyLogFile(File file);
- /**
- * 查询服务状态
- *
- * @param serviceName 服务名称
- * @return true 运行中
- */
- public abstract boolean getServiceStatus(String serviceName);
-
- /**
- * 启动服务
- *
- * @param serviceName 服务名称
- * @return 结果
- */
- public abstract String startService(String serviceName);
-
- /**
- * 关闭服务
- *
- * @param serviceName 服务名称
- * @return 结果
- */
- public abstract String stopService(String serviceName);
+// /**
+// * 查询服务状态
+// *
+// * @param serviceName 服务名称
+// * @return true 运行中
+// */
+// public abstract boolean getServiceStatus(String serviceName);
+//
+// /**
+// * 启动服务
+// *
+// * @param serviceName 服务名称
+// * @return 结果
+// */
+// public abstract String startService(String serviceName);
+//
+// /**
+// * 关闭服务
+// *
+// * @param serviceName 服务名称
+// * @return 结果
+// */
+// public abstract String stopService(String serviceName);
/**
* 构建kill 命令
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/BaseUnixProjectCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/BaseUnixProjectCommander.java
index 618e7e173..48908c914 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/BaseUnixProjectCommander.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/BaseUnixProjectCommander.java
@@ -22,9 +22,14 @@
*/
package org.dromara.jpom.common.commander;
-import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.StrUtil;
+import lombok.Lombok;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.jpom.configuration.ProjectConfig;
import org.dromara.jpom.model.data.NodeProjectInfoModel;
+import org.dromara.jpom.service.manage.ProjectInfoService;
+import org.dromara.jpom.service.script.DslScriptServer;
import org.dromara.jpom.util.CommandUtil;
import org.dromara.jpom.util.JvmUtil;
@@ -40,46 +45,63 @@ import java.util.Optional;
* @author bwcx_jzy
* @since 2021/12/17
*/
+@Slf4j
public abstract class BaseUnixProjectCommander extends AbstractProjectCommander {
-
- public BaseUnixProjectCommander(Charset fileCharset) {
- super(fileCharset);
+ public BaseUnixProjectCommander(Charset fileCharset,
+ SystemCommander systemCommander,
+ ProjectConfig projectConfig,
+ DslScriptServer dslScriptServer,
+ ProjectInfoService projectInfoService) {
+ super(fileCharset, systemCommander, projectConfig, dslScriptServer, projectInfoService);
}
@Override
- public String buildJavaCommand(NodeProjectInfoModel nodeProjectInfoModel) {
- String path = NodeProjectInfoModel.getClassPathLib(nodeProjectInfoModel);
+ public String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel) {
+ NodeProjectInfoModel infoModel = projectInfoService.resolveModel(nodeProjectInfoModel);
+ return this.buildRunCommand(nodeProjectInfoModel, infoModel);
+ }
+
+
+ @Override
+ public String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
+ String lib = projectInfoService.resolveLibPath(originalModel);
+ String path = this.getClassPathLib(originalModel, lib);
if (StrUtil.isBlank(path)) {
return null;
}
String tag = nodeProjectInfoModel.getId();
+ String absoluteLog = projectInfoService.resolveAbsoluteLog(nodeProjectInfoModel, originalModel);
return StrUtil.format("nohup {} {} {} {} {} {} >> {} 2>&1 &",
getRunJavaPath(nodeProjectInfoModel, false),
Optional.ofNullable(nodeProjectInfoModel.getJvm()).orElse(StrUtil.EMPTY),
- JvmUtil.getJpomPidTag(tag, nodeProjectInfoModel.allLib()),
+ JvmUtil.getJpomPidTag(tag, lib),
path,
- Optional.ofNullable(nodeProjectInfoModel.getMainClass()).orElse(StrUtil.EMPTY),
+ Optional.ofNullable(originalModel.mainClass()).orElse(StrUtil.EMPTY),
Optional.ofNullable(nodeProjectInfoModel.getArgs()).orElse(StrUtil.EMPTY),
- nodeProjectInfoModel.getAbsoluteLog());
+ absoluteLog);
}
@Override
- public CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, int pid) throws Exception {
- File file = FileUtil.file(nodeProjectInfoModel.allLib());
+ public CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, int pid) {
+ File file = projectInfoService.resolveLibFile(originalModel);
List result = new ArrayList<>();
boolean success = false;
- String kill = AbstractSystemCommander.getInstance().kill(file, pid);
+ String kill = systemCommander.kill(file, pid);
result.add(kill);
- if (this.loopCheckRun(nodeProjectInfoModel, false)) {
+ if (this.loopCheckRun(nodeProjectInfoModel, originalModel, false)) {
success = true;
} else {
// 强制杀进程
result.add("Kill not completed, test kill -9");
String cmd = String.format("kill -9 %s", pid);
- CommandUtil.asyncExeLocalCommand(file, cmd);
+ try {
+ CommandUtil.asyncExeLocalCommand(cmd, file);
+ } catch (Exception e) {
+ throw Lombok.sneakyThrow(e);
+ }
//
- if (this.loopCheckRun(nodeProjectInfoModel, 5, false)) {
+ if (this.loopCheckRun(nodeProjectInfoModel, originalModel, 5, false)) {
success = true;
} else {
result.add("Kill -9 not completed, kill -9 failed ");
@@ -89,4 +111,24 @@ public abstract class BaseUnixProjectCommander extends AbstractProjectCommander
return CommandOpResult.of(success, status(tag)).appendMsg(result);
// return status(tag) + StrUtil.SPACE + kill;
}
+
+ /**
+ * 尝试ps -ef | grep 中查看进程id
+ *
+ * @param tag 进程标识
+ * @return 运行标识
+ */
+ @Override
+ protected String bySystemPs(String tag) {
+ String execSystemCommand = CommandUtil.execSystemCommand("ps -ef | grep " + tag);
+ log.debug("getPsStatus {} {}", tag, execSystemCommand);
+ List list = StrSplitter.splitTrim(execSystemCommand, StrUtil.LF, true);
+ for (String item : list) {
+ if (JvmUtil.checkCommandLineIsJpom(item, tag)) {
+ String[] split = StrUtil.splitToArray(item, StrUtil.SPACE);
+ return StrUtil.format("{}:{}", AbstractProjectCommander.RUNNING_TAG, split[1]);
+ }
+ }
+ return AbstractProjectCommander.STOP_TAG;
+ }
}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/CommandOpResult.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/CommandOpResult.java
index c06d055c6..b089c14f7 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/CommandOpResult.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/CommandOpResult.java
@@ -26,10 +26,11 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
-import lombok.Getter;
+import lombok.Data;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
/**
* 命令操作执行结果
@@ -37,17 +38,17 @@ import java.util.List;
* @author bwcx_jzy
* @since 2022/11/30
*/
-@Getter
+@Data
public class CommandOpResult {
/**
* 是否成功
*/
- private boolean success;
+ private Boolean success;
/**
* 进程id
*/
- private int pid;
+ private Integer pid;
/**
* 多个进程 id
*/
@@ -65,6 +66,21 @@ public class CommandOpResult {
*/
private final List msgs = new ArrayList<>();
+ /**
+ * 执行是否成功
+ *
+ * @return true 成功
+ */
+ public boolean isSuccess() {
+ return success != null && success;
+ }
+
+ /**
+ * 构建结构对象
+ *
+ * @param msg 结果消息
+ * @return result
+ */
public static CommandOpResult of(String msg) {
int[] pidsArray = null;
String ports = null;
@@ -88,7 +104,7 @@ public class CommandOpResult {
}
public static CommandOpResult of(boolean success) {
- return of(success, null);
+ return of(success, (List) null);
}
public static CommandOpResult of(boolean success, String msg) {
@@ -98,6 +114,13 @@ public class CommandOpResult {
return commandOpResult;
}
+ public static CommandOpResult of(boolean success, List msg) {
+ CommandOpResult commandOpResult = new CommandOpResult();
+ commandOpResult.success = success;
+ Optional.ofNullable(msg).ifPresent(commandOpResult.msgs::addAll);
+ return commandOpResult;
+ }
+
public CommandOpResult appendMsg(String msg) {
if (StrUtil.isEmpty(msg)) {
return this;
@@ -113,13 +136,6 @@ public class CommandOpResult {
return this;
}
- public CommandOpResult appendMsg(String... msgs) {
- for (String msg : msgs) {
- this.appendMsg(msg);
- }
- return this;
- }
-
public String msgStr() {
return CollUtil.join(msgs, StrUtil.COMMA);
}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/Commander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/Commander.java
new file mode 100644
index 000000000..5f67def1b
--- /dev/null
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/Commander.java
@@ -0,0 +1,80 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Code Technology Studio
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.dromara.jpom.common.commander;
+
+import cn.hutool.system.OsInfo;
+import cn.hutool.system.SystemUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.dromara.jpom.system.JpomRuntimeException;
+import org.springframework.context.annotation.Condition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+/**
+ * @author bwcx_jzy
+ * @since 23/12/29 029
+ */
+@Configuration
+@Slf4j
+public class Commander {
+
+ public Commander() {
+ OsInfo osInfo = SystemUtil.getOsInfo();
+ if (osInfo.isLinux()) {
+ // Linux系统
+ log.debug("当前系统为:linux");
+ } else if (osInfo.isWindows()) {
+ // Windows系统
+ log.debug("当前系统为:windows");
+ } else if (osInfo.isMac()) {
+ log.debug("当前系统为:mac");
+ } else {
+ throw new JpomRuntimeException("不支持的:" + osInfo.getName());
+ }
+ }
+
+ public static class Windows implements Condition {
+
+ @Override
+ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ return SystemUtil.getOsInfo().isWindows();
+ }
+ }
+
+ public static class Linux implements Condition {
+
+ @Override
+ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ return SystemUtil.getOsInfo().isLinux();
+ }
+ }
+
+ public static class Mac implements Condition {
+
+ @Override
+ public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+ return SystemUtil.getOsInfo().isMac();
+ }
+ }
+}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/ProjectCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/ProjectCommander.java
new file mode 100644
index 000000000..e682e3473
--- /dev/null
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/ProjectCommander.java
@@ -0,0 +1,87 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Code Technology Studio
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.dromara.jpom.common.commander;
+
+import org.dromara.jpom.model.data.NodeProjectInfoModel;
+import org.dromara.jpom.socket.ConsoleCommandOp;
+
+/**
+ * @author bwcx_jzy
+ * @since 23/12/29 029
+ */
+public interface ProjectCommander {
+
+ /**
+ * 生成可以执行的命令
+ *
+ * @param nodeProjectInfoModel 项目
+ * @return null 是条件不足
+ */
+ String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel);
+
+ /**
+ * 执行 webhooks 通知
+ *
+ * @param nodeProjectInfoModel 项目信息
+ * @param type 类型
+ * @param other 其他参数
+ */
+ void asyncWebHooks(NodeProjectInfoModel nodeProjectInfoModel, String type, Object... other);
+
+
+ /**
+ * 清空日志信息
+ *
+ * @param nodeProjectInfoModel 项目
+ * @return 结果
+ */
+ String backLog(NodeProjectInfoModel nodeProjectInfoModel);
+
+
+ /**
+ * 获取进程占用的主要端口
+ *
+ * @param pid 进程id
+ * @return 端口
+ */
+ String getMainPort(Integer pid);
+
+
+ /**
+ * 是否正在运行
+ *
+ * @param nodeProjectInfoModel 项目
+ * @return true 正在运行
+ */
+ boolean isRun(NodeProjectInfoModel nodeProjectInfoModel);
+
+
+ /**
+ * 执行shell命令
+ *
+ * @param consoleCommandOp 执行的操作
+ * @param nodeProjectInfoModel 项目信息
+ * @return 执行结果
+ */
+ CommandOpResult execCommand(ConsoleCommandOp consoleCommandOp, NodeProjectInfoModel nodeProjectInfoModel);
+}
diff --git a/modules/common/src/main/java/org/dromara/jpom/system/BaseExtConfig.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/SystemCommander.java
similarity index 68%
rename from modules/common/src/main/java/org/dromara/jpom/system/BaseExtConfig.java
rename to modules/agent/src/main/java/org/dromara/jpom/common/commander/SystemCommander.java
index 182015e47..dbb13ecac 100644
--- a/modules/common/src/main/java/org/dromara/jpom/system/BaseExtConfig.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/SystemCommander.java
@@ -20,34 +20,32 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package org.dromara.jpom.system;
+package org.dromara.jpom.common.commander;
-import lombok.Data;
-import org.dromara.jpom.util.BaseFileTailWatcher;
+import java.io.File;
/**
* @author bwcx_jzy
- * @since 2022/12/17
+ * @since 23/12/29 029
*/
-@Data
-public abstract class BaseExtConfig {
- /**
- * 数据目录
- */
- private String path;
+public interface SystemCommander {
/**
- * 初始读取日志文件行号
+ * 清空文件内容
+ *
+ * @param file 文件
+ * @return 执行结果
*/
- private int initReadLine = 10;
+ String emptyLogFile(File file);
- public void setInitReadLine(int initReadLine) {
- this.initReadLine = initReadLine;
- BaseFileTailWatcher.setInitReadLine(this.getInitReadLine());
- }
- public void setPath(String path) {
- this.path = path;
- ExtConfigBean.setPath(path);
- }
+ /**
+ * kill 进程
+ *
+ * @param pid 进程编号
+ * @param file 指定文件夹执行
+ * @return 结束进程命令
+ */
+
+ String kill(File file, int pid);
}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/LinuxProjectCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/LinuxProjectCommander.java
index 121805bb0..d81aab97b 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/LinuxProjectCommander.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/LinuxProjectCommander.java
@@ -25,11 +25,19 @@ package org.dromara.jpom.common.commander.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.StrUtil;
+import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.common.commander.BaseUnixProjectCommander;
+import org.dromara.jpom.common.commander.Commander;
+import org.dromara.jpom.common.commander.SystemCommander;
+import org.dromara.jpom.configuration.AgentConfig;
import org.dromara.jpom.model.system.NetstatModel;
+import org.dromara.jpom.service.manage.ProjectInfoService;
+import org.dromara.jpom.service.script.DslScriptServer;
import org.dromara.jpom.util.CommandUtil;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
-import java.nio.charset.Charset;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -39,10 +47,17 @@ import java.util.stream.Collectors;
*
* @author Administrator
*/
+@Conditional(Commander.Linux.class)
+@Service
+@Primary
+@Slf4j
public class LinuxProjectCommander extends BaseUnixProjectCommander {
- public LinuxProjectCommander(Charset fileCharset) {
- super(fileCharset);
+ public LinuxProjectCommander(AgentConfig agentConfig,
+ SystemCommander systemCommander,
+ DslScriptServer dslScriptServer,
+ ProjectInfoService projectInfoService) {
+ super(agentConfig.getProject().getLog().getFileCharset(), systemCommander, agentConfig.getProject(), dslScriptServer, projectInfoService);
}
@Override
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/LinuxSystemCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/LinuxSystemCommander.java
index 5e74d431d..33c80f818 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/LinuxSystemCommander.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/LinuxSystemCommander.java
@@ -22,22 +22,25 @@
*/
package org.dromara.jpom.common.commander.impl;
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
-import cn.hutool.system.SystemUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.common.commander.AbstractSystemCommander;
+import org.dromara.jpom.common.commander.Commander;
import org.dromara.jpom.util.CommandUtil;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
import java.io.File;
-import java.util.List;
/**
* @author bwcx_jzy
* @since 2019/4/16
*/
@Slf4j
+@Conditional(Commander.Linux.class)
+@Service
+@Primary
public class LinuxSystemCommander extends AbstractSystemCommander {
@@ -47,55 +50,55 @@ public class LinuxSystemCommander extends AbstractSystemCommander {
}
- @Override
- public boolean getServiceStatus(String serviceName) {
- if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
- String ps = getPs(serviceName);
- return StrUtil.isNotEmpty(ps);
- }
- String format = StrUtil.format("service {} status", serviceName);
- String result = CommandUtil.execSystemCommand(format);
- return StrUtil.containsIgnoreCase(result, "RUNNING");
- }
-
- @Override
- public String startService(String serviceName) {
- if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
- try {
- CommandUtil.asyncExeLocalCommand(FileUtil.file(SystemUtil.getUserInfo().getHomeDir()), serviceName);
- return "ok";
- } catch (Exception e) {
- log.error("执行异常", e);
- return "执行异常:" + e.getMessage();
- }
- }
- String format = StrUtil.format("service {} start", serviceName);
- return CommandUtil.execSystemCommand(format);
- }
-
- @Override
- public String stopService(String serviceName) {
- if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
- String ps = getPs(serviceName);
- List list = StrUtil.splitTrim(ps, StrUtil.LF);
- if (list == null || list.isEmpty()) {
- return "stop";
- }
- String s = list.get(0);
- list = StrUtil.splitTrim(s, StrUtil.SPACE);
- if (list == null || list.size() < 2) {
- return "stop";
- }
- File file = new File(SystemUtil.getUserInfo().getHomeDir());
- int pid = Convert.toInt(list.get(1), 0);
- if (pid <= 0) {
- return "error stop";
- }
- return kill(file, pid);
- }
- String format = StrUtil.format("service {} stop", serviceName);
- return CommandUtil.execSystemCommand(format);
- }
+// @Override
+// public boolean getServiceStatus(String serviceName) {
+// if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
+// String ps = getPs(serviceName);
+// return StrUtil.isNotEmpty(ps);
+// }
+// String format = StrUtil.format("service {} status", serviceName);
+// String result = CommandUtil.execSystemCommand(format);
+// return StrUtil.containsIgnoreCase(result, "RUNNING");
+// }
+//
+// @Override
+// public String startService(String serviceName) {
+// if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
+// try {
+// CommandUtil.asyncExeLocalCommand(FileUtil.file(SystemUtil.getUserInfo().getHomeDir()), serviceName);
+// return "ok";
+// } catch (Exception e) {
+// log.error("执行异常", e);
+// return "执行异常:" + e.getMessage();
+// }
+// }
+// String format = StrUtil.format("service {} start", serviceName);
+// return CommandUtil.execSystemCommand(format);
+// }
+//
+// @Override
+// public String stopService(String serviceName) {
+// if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
+// String ps = getPs(serviceName);
+// List list = StrUtil.splitTrim(ps, StrUtil.LF);
+// if (list == null || list.isEmpty()) {
+// return "stop";
+// }
+// String s = list.get(0);
+// list = StrUtil.splitTrim(s, StrUtil.SPACE);
+// if (list == null || list.size() < 2) {
+// return "stop";
+// }
+// File file = new File(SystemUtil.getUserInfo().getHomeDir());
+// int pid = Convert.toInt(list.get(1), 0);
+// if (pid <= 0) {
+// return "error stop";
+// }
+// return kill(file, pid);
+// }
+// String format = StrUtil.format("service {} stop", serviceName);
+// return CommandUtil.execSystemCommand(format);
+// }
@Override
public String buildKill(int pid) {
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/MacOsProjectCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/MacOsProjectCommander.java
index 76204b23f..ce075c9b3 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/MacOsProjectCommander.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/MacOsProjectCommander.java
@@ -26,10 +26,16 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.StrUtil;
import org.dromara.jpom.common.commander.BaseUnixProjectCommander;
+import org.dromara.jpom.common.commander.Commander;
+import org.dromara.jpom.common.commander.SystemCommander;
+import org.dromara.jpom.configuration.AgentConfig;
import org.dromara.jpom.model.system.NetstatModel;
+import org.dromara.jpom.service.manage.ProjectInfoService;
+import org.dromara.jpom.service.script.DslScriptServer;
import org.dromara.jpom.util.CommandUtil;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.stereotype.Service;
-import java.nio.charset.Charset;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@@ -41,10 +47,15 @@ import java.util.stream.Collectors;
*
* @author Hotstrip
*/
+@Conditional(Commander.Mac.class)
+@Service
public class MacOsProjectCommander extends BaseUnixProjectCommander {
- public MacOsProjectCommander(Charset fileCharset) {
- super(fileCharset);
+ public MacOsProjectCommander(AgentConfig agentConfig,
+ SystemCommander systemCommander,
+ DslScriptServer dslScriptServer,
+ ProjectInfoService projectInfoService) {
+ super(agentConfig.getProject().getLog().getFileCharset(), systemCommander, agentConfig.getProject(), dslScriptServer, projectInfoService);
}
@Override
@@ -64,26 +75,29 @@ public class MacOsProjectCommander extends BaseUnixProjectCommander {
if (CollUtil.isEmpty(netList)) {
return null;
}
- return netList.stream().map(str -> {
- List list = StrSplitter.splitTrim(str, " ", true);
- if (list.size() < 10) {
- return null;
- }
- NetstatModel netstatModel = new NetstatModel();
- netstatModel.setProtocol(list.get(7));
- //netstatModel.setReceive(list.get(1));
- //netstatModel.setSend(list.get(2));
- netstatModel.setLocal(list.get(8));
- netstatModel.setForeign(list.get(4));
- if ("tcp".equalsIgnoreCase(netstatModel.getProtocol())) {
- netstatModel.setStatus(CollUtil.get(list, 9));
- netstatModel.setName(CollUtil.get(list, 0));
- } else {
- netstatModel.setStatus(StrUtil.DASHED);
- netstatModel.setName(CollUtil.get(list, 5));
- }
+ return netList.stream()
+ .map(str -> {
+ List list = StrSplitter.splitTrim(str, " ", true);
+ if (list.size() < 10) {
+ return null;
+ }
+ NetstatModel netstatModel = new NetstatModel();
+ netstatModel.setProtocol(list.get(7));
+ //netstatModel.setReceive(list.get(1));
+ //netstatModel.setSend(list.get(2));
+ netstatModel.setLocal(list.get(8));
+ netstatModel.setForeign(list.get(4));
+ if ("tcp".equalsIgnoreCase(netstatModel.getProtocol())) {
+ netstatModel.setStatus(CollUtil.get(list, 9));
+ netstatModel.setName(CollUtil.get(list, 0));
+ } else {
+ netstatModel.setStatus(StrUtil.DASHED);
+ netstatModel.setName(CollUtil.get(list, 5));
+ }
- return netstatModel;
- }).filter(Objects::nonNull).collect(Collectors.toList());
+ return netstatModel;
+ })
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
}
}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/MacOsSystemCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/MacOsSystemCommander.java
index 4515920c5..e0b02d002 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/MacOsSystemCommander.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/MacOsSystemCommander.java
@@ -22,21 +22,21 @@
*/
package org.dromara.jpom.common.commander.impl;
-import cn.hutool.core.convert.Convert;
-import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.util.StrUtil;
-import cn.hutool.system.SystemUtil;
import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.common.commander.AbstractSystemCommander;
+import org.dromara.jpom.common.commander.Commander;
import org.dromara.jpom.util.CommandUtil;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.stereotype.Service;
import java.io.File;
-import java.util.List;
/**
* @author User
*/
@Slf4j
+@Conditional(Commander.Mac.class)
+@Service
public class MacOsSystemCommander extends AbstractSystemCommander {
@@ -46,72 +46,72 @@ public class MacOsSystemCommander extends AbstractSystemCommander {
}
- @Override
- public boolean getServiceStatus(String serviceName) {
- if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
- String ps = getPs(serviceName);
- return StrUtil.isNotEmpty(ps);
- }
- /**
- * Mac OS 里面查询服务的命令是 launchctl list | grep serverName
- * 第一个数字是进程的 PID,如果进程正在运行,如果它不在运行,则显示 "-"
- * 第二个数字是进程的退出代码(如果已完成)。如果为负,则为终止信号的数量
- * 第三列进程名称
- */
- String format = StrUtil.format("service {} status", serviceName);
- String result = CommandUtil.execSystemCommand(format);
- return StrUtil.containsIgnoreCase(result, "RUNNING");
- }
-
- private String getPs(final String serviceName) {
- String ps = StrUtil.format(" ps -ef |grep -w {} | grep -v grep", serviceName);
- return CommandUtil.execSystemCommand(ps);
- }
-
- @Override
- public String startService(String serviceName) {
- if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
- try {
- CommandUtil.asyncExeLocalCommand(FileUtil.file(SystemUtil.getUserInfo().getHomeDir()), serviceName);
- return "ok";
- } catch (Exception e) {
- log.error("执行异常", e);
- return "执行异常:" + e.getMessage();
- }
- }
- /**
- * Mac OS 里面启动服务命令是 launchctl start serverName
- */
- String format = StrUtil.format("service {} start", serviceName);
- return CommandUtil.execSystemCommand(format);
- }
-
- @Override
- public String stopService(String serviceName) {
- if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
- String ps = getPs(serviceName);
- List list = StrUtil.splitTrim(ps, StrUtil.LF);
- if (list == null || list.isEmpty()) {
- return "stop";
- }
- String s = list.get(0);
- list = StrUtil.splitTrim(s, StrUtil.SPACE);
- if (list == null || list.size() < 2) {
- return "stop";
- }
- File file = new File(SystemUtil.getUserInfo().getHomeDir());
- int pid = Convert.toInt(list.get(1), 0);
- if (pid <= 0) {
- return "error stop";
- }
- return kill(file, pid);
- }
- /**
- * Mac OS 里面启动服务命令是 launchctl stop serverName
- */
- String format = StrUtil.format("service {} stop", serviceName);
- return CommandUtil.execSystemCommand(format);
- }
+// @Override
+// public boolean getServiceStatus(String serviceName) {
+// if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
+// String ps = getPs(serviceName);
+// return StrUtil.isNotEmpty(ps);
+// }
+// /**
+// * Mac OS 里面查询服务的命令是 launchctl list | grep serverName
+// * 第一个数字是进程的 PID,如果进程正在运行,如果它不在运行,则显示 "-"
+// * 第二个数字是进程的退出代码(如果已完成)。如果为负,则为终止信号的数量
+// * 第三列进程名称
+// */
+// String format = StrUtil.format("service {} status", serviceName);
+// String result = CommandUtil.execSystemCommand(format);
+// return StrUtil.containsIgnoreCase(result, "RUNNING");
+// }
+//
+// private String getPs(final String serviceName) {
+// String ps = StrUtil.format(" ps -ef |grep -w {} | grep -v grep", serviceName);
+// return CommandUtil.execSystemCommand(ps);
+// }
+//
+// @Override
+// public String startService(String serviceName) {
+// if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
+// try {
+// CommandUtil.asyncExeLocalCommand(FileUtil.file(SystemUtil.getUserInfo().getHomeDir()), serviceName);
+// return "ok";
+// } catch (Exception e) {
+// log.error("执行异常", e);
+// return "执行异常:" + e.getMessage();
+// }
+// }
+// /**
+// * Mac OS 里面启动服务命令是 launchctl start serverName
+// */
+// String format = StrUtil.format("service {} start", serviceName);
+// return CommandUtil.execSystemCommand(format);
+// }
+//
+// @Override
+// public String stopService(String serviceName) {
+// if (StrUtil.startWith(serviceName, StrUtil.SLASH)) {
+// String ps = getPs(serviceName);
+// List list = StrUtil.splitTrim(ps, StrUtil.LF);
+// if (list == null || list.isEmpty()) {
+// return "stop";
+// }
+// String s = list.get(0);
+// list = StrUtil.splitTrim(s, StrUtil.SPACE);
+// if (list == null || list.size() < 2) {
+// return "stop";
+// }
+// File file = new File(SystemUtil.getUserInfo().getHomeDir());
+// int pid = Convert.toInt(list.get(1), 0);
+// if (pid <= 0) {
+// return "error stop";
+// }
+// return kill(file, pid);
+// }
+// /**
+// * Mac OS 里面启动服务命令是 launchctl stop serverName
+// */
+// String format = StrUtil.format("service {} stop", serviceName);
+// return CommandUtil.execSystemCommand(format);
+// }
@Override
public String buildKill(int pid) {
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/WindowsProjectCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/WindowsProjectCommander.java
index b9702fdfa..3516bb6e5 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/WindowsProjectCommander.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/WindowsProjectCommander.java
@@ -22,18 +22,23 @@
*/
package org.dromara.jpom.common.commander.impl;
-import cn.hutool.core.io.FileUtil;
import cn.hutool.core.text.StrSplitter;
import cn.hutool.core.util.StrUtil;
import org.dromara.jpom.common.commander.AbstractProjectCommander;
-import org.dromara.jpom.common.commander.AbstractSystemCommander;
import org.dromara.jpom.common.commander.CommandOpResult;
+import org.dromara.jpom.common.commander.Commander;
+import org.dromara.jpom.common.commander.SystemCommander;
+import org.dromara.jpom.configuration.AgentConfig;
import org.dromara.jpom.model.data.NodeProjectInfoModel;
import org.dromara.jpom.model.system.NetstatModel;
+import org.dromara.jpom.service.manage.ProjectInfoService;
+import org.dromara.jpom.service.script.DslScriptServer;
import org.dromara.jpom.util.CommandUtil;
import org.dromara.jpom.util.JvmUtil;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.stereotype.Service;
-import java.nio.charset.Charset;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@@ -43,43 +48,57 @@ import java.util.Optional;
*
* @author Administrator
*/
+@Conditional(Commander.Windows.class)
+@Service
public class WindowsProjectCommander extends AbstractProjectCommander {
-
- public WindowsProjectCommander(Charset fileCharset) {
- super(fileCharset);
+ public WindowsProjectCommander(AgentConfig agentConfig,
+ SystemCommander systemCommander,
+ DslScriptServer dslScriptServer,
+ ProjectInfoService projectInfoService) {
+ super(agentConfig.getProject().getLog().getFileCharset(), systemCommander, agentConfig.getProject(), dslScriptServer, projectInfoService);
}
@Override
- public String buildJavaCommand(NodeProjectInfoModel nodeProjectInfoModel) {
- String classPath = NodeProjectInfoModel.getClassPathLib(nodeProjectInfoModel);
+ public String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel) {
+ NodeProjectInfoModel infoModel = projectInfoService.resolveModel(nodeProjectInfoModel);
+ return this.buildRunCommand(nodeProjectInfoModel, infoModel);
+ }
+
+ @Override
+ public String buildRunCommand(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel) {
+ String lib = projectInfoService.resolveLibPath(originalModel);
+ String classPath = this.getClassPathLib(originalModel, lib);
if (StrUtil.isBlank(classPath)) {
return null;
}
// 拼接命令
String jvm = nodeProjectInfoModel.getJvm();
String tag = nodeProjectInfoModel.getId();
- String mainClass = nodeProjectInfoModel.getMainClass();
+ String mainClass = originalModel.mainClass();
String args = nodeProjectInfoModel.getArgs();
+
+ String absoluteLog = projectInfoService.resolveAbsoluteLog(nodeProjectInfoModel, originalModel);
return StrUtil.format("{} {} {} {} {} {} >> {} &",
getRunJavaPath(nodeProjectInfoModel, true),
Optional.ofNullable(jvm).orElse(StrUtil.EMPTY),
- JvmUtil.getJpomPidTag(tag, nodeProjectInfoModel.allLib()),
+ JvmUtil.getJpomPidTag(tag, lib),
classPath,
Optional.ofNullable(mainClass).orElse(StrUtil.EMPTY),
Optional.ofNullable(args).orElse(StrUtil.EMPTY),
- nodeProjectInfoModel.getAbsoluteLog());
+ absoluteLog);
}
@Override
- public CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, int pid) throws Exception {
+ public CommandOpResult stopJava(NodeProjectInfoModel nodeProjectInfoModel, NodeProjectInfoModel originalModel, int pid) {
String tag = nodeProjectInfoModel.getId();
List result = new ArrayList<>();
boolean success = false;
// 如果正在运行,则执行杀进程命令
- String kill = AbstractSystemCommander.getInstance().kill(FileUtil.file(nodeProjectInfoModel.allLib()), pid);
+ File file = projectInfoService.resolveLibFile(nodeProjectInfoModel);
+ String kill = systemCommander.kill(file, pid);
result.add(kill);
- if (this.loopCheckRun(nodeProjectInfoModel, false)) {
+ if (this.loopCheckRun(nodeProjectInfoModel, originalModel, false)) {
success = true;
} else {
result.add("Kill not completed");
@@ -117,4 +136,7 @@ public class WindowsProjectCommander extends AbstractProjectCommander {
}
return array;
}
+
+ // tasklist | findstr /s /i "java"
+ // wmic process where caption="javaw.exe" get processid,caption,commandline /value
}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/WindowsSystemCommander.java b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/WindowsSystemCommander.java
index 0d264a659..08565708c 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/WindowsSystemCommander.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/commander/impl/WindowsSystemCommander.java
@@ -22,9 +22,11 @@
*/
package org.dromara.jpom.common.commander.impl;
-import cn.hutool.core.util.StrUtil;
import org.dromara.jpom.common.commander.AbstractSystemCommander;
+import org.dromara.jpom.common.commander.Commander;
import org.dromara.jpom.util.CommandUtil;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.stereotype.Service;
import java.io.File;
@@ -34,6 +36,8 @@ import java.io.File;
* @author bwcx_jzy
* @since 2019/4/16
*/
+@Conditional(Commander.Windows.class)
+@Service
public class WindowsSystemCommander extends AbstractSystemCommander {
@Override
@@ -42,23 +46,23 @@ public class WindowsSystemCommander extends AbstractSystemCommander {
}
- @Override
- public boolean getServiceStatus(String serviceName) {
- String result = CommandUtil.execSystemCommand("sc query " + serviceName);
- return StrUtil.containsIgnoreCase(result, "RUNNING");
- }
-
- @Override
- public String startService(String serviceName) {
- String format = StrUtil.format("net start {}", serviceName);
- return CommandUtil.execSystemCommand(format);
- }
-
- @Override
- public String stopService(String serviceName) {
- String format = StrUtil.format("net stop {}", serviceName);
- return CommandUtil.execSystemCommand(format);
- }
+// @Override
+// public boolean getServiceStatus(String serviceName) {
+// String result = CommandUtil.execSystemCommand("sc query " + serviceName);
+// return StrUtil.containsIgnoreCase(result, "RUNNING");
+// }
+//
+// @Override
+// public String startService(String serviceName) {
+// String format = StrUtil.format("net start {}", serviceName);
+// return CommandUtil.execSystemCommand(format);
+// }
+//
+// @Override
+// public String stopService(String serviceName) {
+// String format = StrUtil.format("net stop {}", serviceName);
+// return CommandUtil.execSystemCommand(format);
+// }
@Override
public String buildKill(int pid) {
diff --git a/modules/agent/src/main/java/org/dromara/jpom/common/interceptor/AuthorizeInterceptor.java b/modules/agent/src/main/java/org/dromara/jpom/common/interceptor/AuthorizeInterceptor.java
index 5e2b262f8..98e146212 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/common/interceptor/AuthorizeInterceptor.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/common/interceptor/AuthorizeInterceptor.java
@@ -26,7 +26,8 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.keepbx.jpom.model.JsonMessage;
import org.dromara.jpom.common.Const;
-import org.dromara.jpom.system.AgentAuthorize;
+import org.dromara.jpom.configuration.AgentConfig;
+import org.dromara.jpom.configuration.AgentAuthorize;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.method.HandlerMethod;
@@ -45,8 +46,8 @@ public class AuthorizeInterceptor implements HandlerMethodInterceptor {
private final AgentAuthorize agentAuthorize;
- public AuthorizeInterceptor(AgentAuthorize agentAuthorize) {
- this.agentAuthorize = agentAuthorize;
+ public AuthorizeInterceptor(AgentConfig agentConfig) {
+ this.agentAuthorize = agentConfig.getAuthorize();
}
@Override
diff --git a/modules/agent/src/main/java/org/dromara/jpom/system/AgentAuthorize.java b/modules/agent/src/main/java/org/dromara/jpom/configuration/AgentAuthorize.java
similarity index 83%
rename from modules/agent/src/main/java/org/dromara/jpom/system/AgentAuthorize.java
rename to modules/agent/src/main/java/org/dromara/jpom/configuration/AgentAuthorize.java
index 2a1d0dafb..5920992e8 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/system/AgentAuthorize.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/configuration/AgentAuthorize.java
@@ -20,7 +20,7 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package org.dromara.jpom.system;
+package org.dromara.jpom.configuration;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
@@ -32,13 +32,11 @@ import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.JpomApplication;
import org.dromara.jpom.common.Const;
-import org.dromara.jpom.common.ILoadEvent;
import org.dromara.jpom.model.system.AgentAutoUser;
+import org.dromara.jpom.system.JpomRuntimeException;
import org.dromara.jpom.util.JsonFileUtil;
import org.dromara.jpom.util.JvmUtil;
import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Configuration;
import java.io.File;
@@ -50,9 +48,8 @@ import java.io.File;
*/
@Slf4j
@Data
-@Configuration
@ConfigurationProperties("jpom.authorize")
-public class AgentAuthorize implements ILoadEvent {
+public class AgentAuthorize {
/**
* 账号
*/
@@ -74,17 +71,6 @@ public class AgentAuthorize implements ILoadEvent {
return null;
}
- private final JpomApplication configBean;
- /**
- * 注入控制加载顺序,必须先加载数据目录才能初始化
- */
- private final AgentConfig agentConfig;
-
- public AgentAuthorize(JpomApplication configBean,
- AgentConfig agentConfig) {
- this.configBean = configBean;
- this.agentConfig = agentConfig;
- }
/**
* 判断授权是否正确
@@ -99,7 +85,7 @@ public class AgentAuthorize implements ILoadEvent {
/**
* 检查是否配置密码
*/
- private void checkPwd() {
+ private void checkPwd(JpomApplication configBean) {
File path = FileUtil.file(configBean.getDataPath(), Const.AUTHORIZE);
if (StrUtil.isNotEmpty(agentPwd)) {
// 有指定密码 清除旧密码信息
@@ -130,14 +116,12 @@ public class AgentAuthorize implements ILoadEvent {
log.info("Automatically generate authorized account:{} password:{} Authorization information storage location:{}", this.agentName, this.agentPwd, FileUtil.getAbsolutePath(path));
}
- @Override
- public void afterPropertiesSet(ApplicationContext applicationContext) throws Exception {
- // 登录名不能为空
+ public void init(JpomApplication configBean) {
if (StrUtil.isEmpty(this.agentName)) {
throw new JpomRuntimeException("The agent login name cannot be empty");
}
if (StrUtil.isEmpty(this.authorize)) {
- this.checkPwd();
+ this.checkPwd(configBean);
// 生成密码授权字符串
this.authorize = SecureUtil.sha1(this.agentName + "@" + this.agentPwd);
} else {
@@ -146,9 +130,4 @@ public class AgentAuthorize implements ILoadEvent {
//
JvmUtil.checkJpsNormal();
}
-
- @Override
- public int getOrder() {
- return HIGHEST_PRECEDENCE;
- }
}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/system/AgentConfig.java b/modules/agent/src/main/java/org/dromara/jpom/configuration/AgentConfig.java
similarity index 50%
rename from modules/agent/src/main/java/org/dromara/jpom/system/AgentConfig.java
rename to modules/agent/src/main/java/org/dromara/jpom/configuration/AgentConfig.java
index 60a155978..1687c4dc5 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/system/AgentConfig.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/configuration/AgentConfig.java
@@ -20,23 +20,24 @@
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-package org.dromara.jpom.system;
+package org.dromara.jpom.configuration;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.io.FileUtil;
-import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.IdUtil;
-import cn.hutool.extra.spring.SpringUtil;
-import cn.hutool.system.SystemUtil;
+import cn.hutool.core.util.ObjectUtil;
import lombok.Data;
-import lombok.EqualsAndHashCode;
import org.dromara.jpom.JpomApplication;
+import org.dromara.jpom.common.ILoadEvent;
+import org.dromara.jpom.system.ExtConfigBean;
+import org.dromara.jpom.util.BaseFileTailWatcher;
+import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
-import org.springframework.util.unit.DataSize;
import java.io.File;
-import java.nio.charset.Charset;
import java.util.Optional;
/**
@@ -45,11 +46,12 @@ import java.util.Optional;
* @author bwcx_jzy
* @since 2022/12/16
*/
-@EqualsAndHashCode(callSuper = true)
+
@Configuration
@ConfigurationProperties("jpom")
@Data
-public class AgentConfig extends BaseExtConfig {
+@EnableConfigurationProperties({ProjectConfig.class, ProjectLogConfig.class, SystemConfig.class, AgentAuthorize.class})
+public class AgentConfig implements ILoadEvent, InitializingBean {
private final JpomApplication jpomApplication;
@@ -58,21 +60,34 @@ public class AgentConfig extends BaseExtConfig {
}
/**
- * 白名单配置
+ * 授权配置
*/
- private WhitelistDirectory whitelist;
-
- public WhitelistDirectory getWhitelist() {
- return Optional.ofNullable(this.whitelist).orElseGet(() -> {
- this.whitelist = new WhitelistDirectory();
- return this.whitelist;
- });
- }
+ private AgentAuthorize authorize;
/**
* 项目配置
*/
private ProjectConfig project;
+ /**
+ * 系统配置参数
+ */
+ private SystemConfig system;
+ /**
+ * 数据目录
+ */
+ private String path;
+
+ /**
+ * 初始读取日志文件行号
+ */
+ private int initReadLine = 10;
+
+ public AgentAuthorize getAuthorize() {
+ return Optional.ofNullable(this.authorize).orElseGet(() -> {
+ this.authorize = new AgentAuthorize();
+ return this.authorize;
+ });
+ }
public ProjectConfig getProject() {
return Optional.ofNullable(this.project).orElseGet(() -> {
@@ -81,13 +96,6 @@ public class AgentConfig extends BaseExtConfig {
});
}
-
- /**
- * 系统配置参数
- */
- private SystemConfig system;
-
-
public SystemConfig getSystem() {
return Optional.ofNullable(this.system).orElseGet(() -> {
this.system = new SystemConfig();
@@ -129,95 +137,22 @@ public class AgentConfig extends BaseExtConfig {
return file;
}
- @Data
- public static class ProjectConfig {
- private LogConfig log;
-
- public LogConfig getLog() {
- return Optional.ofNullable(this.log).orElseGet(() -> {
- this.log = new LogConfig();
- return this.log;
- });
- }
-
- /**
- * 停止项目等待的时长 单位秒,最小为1秒
- */
- private int statusWaitTime = 10;
-
- /**
- * 项目状态检测间隔时间 单位毫秒,最小为1毫秒
- */
- private int statusDetectionInterval = 500;
-
- /**
- * 项目文件备份保留个数,大于 1 才会备份
- */
- private int fileBackupCount;
-
- /**
- * 限制备份指定文件后缀(支持正则)
- * [ '.jar','.html','^.+\\.(?i)(txt)$' ]
- */
- private String[] fileBackupSuffix;
-
- @Data
- public static class LogConfig {
- /**
- * 检测控制台日志周期,防止日志文件过大,目前暂只支持linux 不停服备份
- */
- private String autoBackupConsoleCron = "0 0/10 * * * ?";
- /**
- * 当文件多大时自动备份
- *
- * @see ch.qos.logback.core.util.FileSize
- */
- private DataSize autoBackupSize = DataSize.ofMegabytes(50);
- /**
- * 是否自动将控制台日志文件备份
- */
- private boolean autoBackupToFile = true;
-
- /**
- * 控制台日志保存时长单位天
- */
- private int saveDays = 7;
-
- public int getSaveDays() {
- return Math.max(saveDays, 0);
- }
-
- /**
- * 日志文件的编码格式
- */
- private Charset fileCharset;
-
- public Charset getFileCharset() {
- return Optional.ofNullable(this.fileCharset).orElseGet(() ->
- SystemUtil.getOsInfo().isWindows() ?
- CharsetUtil.CHARSET_GBK : CharsetUtil.CHARSET_UTF_8);
- }
- }
-
-
- public static ProjectConfig getInstance() {
- AgentConfig agentConfig = SpringUtil.getBean(AgentConfig.class);
- return agentConfig.getProject();
- }
+ @Override
+ public void afterPropertiesSet(ApplicationContext applicationContext) throws Exception {
+ // 登录名不能为空
+ this.getAuthorize().init(jpomApplication);
}
- @Data
- public static class WhitelistDirectory {
- /**
- * 白名单目录是否验证包含关系
- */
- private boolean checkStartsWith = true;
+ @Override
+ public int getOrder() {
+ return HIGHEST_PRECEDENCE;
}
- @EqualsAndHashCode(callSuper = true)
- @Data
- public static class SystemConfig extends BaseSystemConfig {
-
+ @Override
+ public void afterPropertiesSet() throws Exception {
+ int initReadLine = ObjectUtil.defaultIfNull(this.initReadLine, 10);
+ BaseFileTailWatcher.setInitReadLine(initReadLine);
+ ExtConfigBean.setPath(path);
}
}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/configuration/ProjectConfig.java b/modules/agent/src/main/java/org/dromara/jpom/configuration/ProjectConfig.java
new file mode 100644
index 000000000..c197ea5c6
--- /dev/null
+++ b/modules/agent/src/main/java/org/dromara/jpom/configuration/ProjectConfig.java
@@ -0,0 +1,68 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Code Technology Studio
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.dromara.jpom.configuration;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import java.util.Optional;
+
+/**
+ * @author bwcx_jzy
+ * @since 23/12/29 029
+ */
+@Data
+@ConfigurationProperties("jpom.project")
+public class ProjectConfig {
+ /**
+ * 项目日志配置
+ */
+ private ProjectLogConfig log;
+ /**
+ * 停止项目等待的时长 单位秒,最小为1秒
+ */
+ private int statusWaitTime = 10;
+
+ /**
+ * 项目状态检测间隔时间 单位毫秒,最小为1毫秒
+ */
+ private int statusDetectionInterval = 500;
+
+ /**
+ * 项目文件备份保留个数,大于 1 才会备份
+ */
+ private int fileBackupCount;
+
+ /**
+ * 限制备份指定文件后缀(支持正则)
+ * [ '.jar','.html','^.+\\.(?i)(txt)$' ]
+ */
+ private String[] fileBackupSuffix;
+
+ public ProjectLogConfig getLog() {
+ return Optional.ofNullable(this.log).orElseGet(() -> {
+ this.log = new ProjectLogConfig();
+ return this.log;
+ });
+ }
+}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/configuration/ProjectLogConfig.java b/modules/agent/src/main/java/org/dromara/jpom/configuration/ProjectLogConfig.java
new file mode 100644
index 000000000..3a7cfa02e
--- /dev/null
+++ b/modules/agent/src/main/java/org/dromara/jpom/configuration/ProjectLogConfig.java
@@ -0,0 +1,75 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Code Technology Studio
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.dromara.jpom.configuration;
+
+import cn.hutool.core.util.CharsetUtil;
+import cn.hutool.system.SystemUtil;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.util.unit.DataSize;
+
+import java.nio.charset.Charset;
+import java.util.Optional;
+
+/**
+ * @author bwcx_jzy
+ * @since 23/12/29 029
+ */
+@Data
+@ConfigurationProperties("jpom.project.log")
+public class ProjectLogConfig {
+ /**
+ * 检测控制台日志周期,防止日志文件过大,目前暂只支持linux 不停服备份
+ */
+ private String autoBackupConsoleCron = "0 0/10 * * * ?";
+ /**
+ * 当文件多大时自动备份
+ *
+ * @see ch.qos.logback.core.util.FileSize
+ */
+ private DataSize autoBackupSize = DataSize.ofMegabytes(50);
+ /**
+ * 是否自动将控制台日志文件备份
+ */
+ private boolean autoBackupToFile = true;
+
+ /**
+ * 控制台日志保存时长单位天
+ */
+ private int saveDays = 7;
+
+ public int getSaveDays() {
+ return Math.max(saveDays, 0);
+ }
+
+ /**
+ * 日志文件的编码格式
+ */
+ private Charset fileCharset;
+
+ public Charset getFileCharset() {
+ return Optional.ofNullable(this.fileCharset).orElseGet(() ->
+ SystemUtil.getOsInfo().isWindows() ?
+ CharsetUtil.CHARSET_GBK : CharsetUtil.CHARSET_UTF_8);
+ }
+}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/configuration/SystemConfig.java b/modules/agent/src/main/java/org/dromara/jpom/configuration/SystemConfig.java
new file mode 100644
index 000000000..7841de7b8
--- /dev/null
+++ b/modules/agent/src/main/java/org/dromara/jpom/configuration/SystemConfig.java
@@ -0,0 +1,38 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Code Technology Studio
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.dromara.jpom.configuration;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.dromara.jpom.system.BaseSystemConfig;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * @author bwcx_jzy
+ * @since 23/12/29 029
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@ConfigurationProperties("jpom.system")
+public class SystemConfig extends BaseSystemConfig {
+}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/controller/IndexController.java b/modules/agent/src/main/java/org/dromara/jpom/controller/IndexController.java
index 5ed325174..f3e87afce 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/controller/IndexController.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/controller/IndexController.java
@@ -33,8 +33,8 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.common.BaseAgentController;
import org.dromara.jpom.common.JpomManifest;
import org.dromara.jpom.common.RemoteVersion;
-import org.dromara.jpom.common.commander.AbstractProjectCommander;
-import org.dromara.jpom.common.commander.AbstractSystemCommander;
+import org.dromara.jpom.common.commander.ProjectCommander;
+import org.dromara.jpom.common.commander.SystemCommander;
import org.dromara.jpom.common.interceptor.NotAuthorize;
import org.dromara.jpom.model.data.NodeProjectInfoModel;
import org.dromara.jpom.model.data.NodeScriptModel;
@@ -50,7 +50,9 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -65,11 +67,17 @@ public class IndexController extends BaseAgentController {
private final ProjectInfoService projectInfoService;
private final NodeScriptServer nodeScriptServer;
+ private final SystemCommander systemCommander;
+ private final ProjectCommander projectCommander;
public IndexController(ProjectInfoService projectInfoService,
- NodeScriptServer nodeScriptServer) {
+ NodeScriptServer nodeScriptServer,
+ SystemCommander systemCommander,
+ ProjectCommander projectCommander) {
this.projectInfoService = projectInfoService;
this.nodeScriptServer = nodeScriptServer;
+ this.systemCommander = systemCommander;
+ this.projectCommander = projectCommander;
}
@RequestMapping(value = {"index", "", "index.html", "/"}, produces = MediaType.TEXT_PLAIN_VALUE)
@@ -125,9 +133,33 @@ public class IndexController extends BaseAgentController {
jsonObject.put("totalMemory", SystemUtil.getTotalMemory());
//
jsonObject.put("freeMemory", SystemUtil.getFreeMemory());
+ Map workspaceMap = new HashMap<>(4);
//
- jsonObject.put("projectCount", CollUtil.size(nodeProjectInfoModels));
- jsonObject.put("scriptCount", CollUtil.size(list));
+ {
+ for (NodeProjectInfoModel model : nodeProjectInfoModels) {
+ JSONObject jsonObject1 = workspaceMap.computeIfAbsent(model.getWorkspaceId(), s -> {
+ JSONObject jsonObject11 = new JSONObject();
+ jsonObject11.put("projectCount", 0);
+ jsonObject11.put("scriptCount", 0);
+ return jsonObject11;
+ });
+ jsonObject1.merge("projectCount", 1, (v1, v2) -> Integer.sum((Integer) v1, (Integer) v2));
+ }
+ jsonObject.put("projectCount", CollUtil.size(nodeProjectInfoModels));
+ }
+ {
+ for (NodeScriptModel model : list) {
+ JSONObject jsonObject1 = workspaceMap.computeIfAbsent(model.getWorkspaceId(), s -> {
+ JSONObject jsonObject11 = new JSONObject();
+ jsonObject11.put("projectCount", 0);
+ jsonObject11.put("scriptCount", 0);
+ return jsonObject11;
+ });
+ jsonObject1.merge("scriptCount", 1, (v1, v2) -> Integer.sum((Integer) v1, (Integer) v2));
+ }
+ jsonObject.put("scriptCount", CollUtil.size(list));
+ }
+ jsonObject.put("workspaceStat", workspaceMap);
return jsonObject;
}
@@ -139,7 +171,7 @@ public class IndexController extends BaseAgentController {
processes = processes.stream()
.peek(jsonObject -> {
int processId = jsonObject.getIntValue("processId");
- String port = AbstractProjectCommander.getInstance().getMainPort(processId);
+ String port = projectCommander.getMainPort(processId);
jsonObject.put("port", port);
//
})
@@ -152,7 +184,7 @@ public class IndexController extends BaseAgentController {
public IJsonMessage kill(int pid) {
long jpomAgentId = JpomManifest.getInstance().getPid();
Assert.state(!StrUtil.equals(StrUtil.toString(jpomAgentId), StrUtil.toString(pid)), "不支持在线关闭 Agent 进程");
- String result = AbstractSystemCommander.getInstance().kill(null, pid);
+ String result = systemCommander.kill(null, pid);
if (StrUtil.isEmpty(result)) {
result = "成功kill";
}
diff --git a/modules/agent/src/main/java/org/dromara/jpom/controller/manage/FileManageController.java b/modules/agent/src/main/java/org/dromara/jpom/controller/manage/FileManageController.java
index 40864f33a..241cb9810 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/controller/manage/FileManageController.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/controller/manage/FileManageController.java
@@ -30,7 +30,7 @@ import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.common.BaseAgentController;
import org.dromara.jpom.common.commander.CommandOpResult;
import org.dromara.jpom.common.validator.ValidatorItem;
-import org.dromara.jpom.system.AgentConfig;
+import org.dromara.jpom.configuration.AgentConfig;
import org.dromara.jpom.util.CompressionFileUtil;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
diff --git a/modules/agent/src/main/java/org/dromara/jpom/controller/manage/ManageEditProjectController.java b/modules/agent/src/main/java/org/dromara/jpom/controller/manage/ManageEditProjectController.java
index 8f9ec6852..9d65cb1a1 100644
--- a/modules/agent/src/main/java/org/dromara/jpom/controller/manage/ManageEditProjectController.java
+++ b/modules/agent/src/main/java/org/dromara/jpom/controller/manage/ManageEditProjectController.java
@@ -26,18 +26,18 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.RegexPool;
import cn.hutool.core.lang.Validator;
-import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.StrUtil;
import cn.keepbx.jpom.IJsonMessage;
import cn.keepbx.jpom.model.JsonMessage;
import lombok.extern.slf4j.Slf4j;
import org.dromara.jpom.common.BaseAgentController;
import org.dromara.jpom.common.Const;
-import org.dromara.jpom.common.commander.AbstractProjectCommander;
+import org.dromara.jpom.common.commander.ProjectCommander;
import org.dromara.jpom.model.RunMode;
import org.dromara.jpom.model.data.DslYmlDto;
import org.dromara.jpom.model.data.NodeProjectInfoModel;
import org.dromara.jpom.service.WhitelistDirectoryService;
+import org.dromara.jpom.socket.ConsoleCommandOp;
import org.dromara.jpom.util.CommandUtil;
import org.dromara.jpom.util.FileUtils;
import org.springframework.http.MediaType;
@@ -61,70 +61,78 @@ import java.util.List;
public class ManageEditProjectController extends BaseAgentController {
private final WhitelistDirectoryService whitelistDirectoryService;
+ private final ProjectCommander projectCommander;
- public ManageEditProjectController(WhitelistDirectoryService whitelistDirectoryService) {
+ public ManageEditProjectController(WhitelistDirectoryService whitelistDirectoryService,
+ ProjectCommander projectCommander) {
this.whitelistDirectoryService = whitelistDirectoryService;
+ this.projectCommander = projectCommander;
}
/**
* 基础检查
*
- * @param projectInfo 项目实体
- * @param whitelistDirectory 白名单
- * @param previewData 预检查数据
+ * @param projectInfo 项目实体
+ * @param previewData 预检查数据
*/
- private NodeProjectInfoModel checkParameter(NodeProjectInfoModel projectInfo,
- String whitelistDirectory,
- boolean previewData) {
+ private void checkParameter(NodeProjectInfoModel projectInfo, boolean previewData) {
String id = projectInfo.getId();
// 兼容 _
String checkId = StrUtil.replace(id, StrUtil.DASHED, StrUtil.UNDERLINE);
Validator.validateGeneral(checkId, 2, Const.ID_MAX_LEN, "项目id 长度范围2-20(英文字母 、数字和下划线)");
Assert.state(!Const.SYSTEM_ID.equals(id), "项目id " + Const.SYSTEM_ID + " 关键词被系统占用");
// 运行模式
- String runModeStr = getParameter("runMode");
- RunMode runMode1 = EnumUtil.fromString(RunMode.class, runModeStr, RunMode.ClassPath);
- projectInfo.setRunMode(runMode1);
+ RunMode runMode = projectInfo.getRunMode();
+ Assert.notNull(runMode, "请选择运行模式");
// 监测
- if (runMode1 == RunMode.ClassPath || runMode1 == RunMode.JavaExtDirsCp) {
- Assert.hasText(projectInfo.getMainClass(), "ClassPath、JavaExtDirsCp 模式 MainClass必填");
- } else if (runMode1 == RunMode.Jar || runMode1 == RunMode.JarWar) {
+ if (runMode == RunMode.ClassPath || runMode == RunMode.JavaExtDirsCp) {
+ Assert.hasText(projectInfo.mainClass(), "ClassPath、JavaExtDirsCp 模式 MainClass必填");
+ if (runMode == RunMode.JavaExtDirsCp) {
+ Assert.hasText(projectInfo.javaExtDirsCp(), "JavaExtDirsCp 模式 javaExtDirsCp必填");
+ }
+ } else if (runMode == RunMode.Jar || runMode == RunMode.JarWar) {
projectInfo.setMainClass(StrUtil.EMPTY);
- }
- if (runMode1 == RunMode.JavaExtDirsCp) {
- Assert.hasText(projectInfo.getJavaExtDirsCp(), "JavaExtDirsCp 模式 javaExtDirsCp必填");
+ } else if (runMode == RunMode.Link) {
+ String linkId = projectInfo.getLinkId();
+ Assert.hasText(linkId, "Link 模式 LinkId必填");
+ NodeProjectInfoModel item = projectInfoService.getItem(linkId);
+ Assert.notNull(item, "软链的项目部存在");
+ RunMode itemRunMode = item.getRunMode();
+ Assert.state(itemRunMode != RunMode.File && itemRunMode != RunMode.Link, "被软链的项目不能是File或Link模式");
}
// 判断是否为分发添加
String strOutGivingProject = getParameter("outGivingProject");
boolean outGivingProject = Boolean.parseBoolean(strOutGivingProject);
projectInfo.setOutGivingProject(outGivingProject);
- if (!previewData) {
- // 不是预检查数据才效验白名单
- if (!whitelistDirectoryService.checkProjectDirectory(whitelistDirectory)) {
- if (outGivingProject) {
- whitelistDirectoryService.addProjectWhiteList(whitelistDirectory);
- } else {
- throw new IllegalArgumentException("请选择正确的项目路径,或者还没有配置白名单");
- }
- }
- String logPath = projectInfo.getLogPath();
- if (StrUtil.isNotEmpty(logPath)) {
- if (!whitelistDirectoryService.checkProjectDirectory(logPath)) {
+ if (runMode != RunMode.Link) {
+ if (!previewData) {
+ String whitelistDirectory = projectInfo.whitelistDirectory();
+ // 不是预检查数据才效验授权
+ if (!whitelistDirectoryService.checkProjectDirectory(whitelistDirectory)) {
if (outGivingProject) {
- whitelistDirectoryService.addProjectWhiteList(logPath);
+ whitelistDirectoryService.addProjectWhiteList(whitelistDirectory);
} else {
- throw new IllegalArgumentException("请填写的项目日志存储路径,或者还没有配置白名单");
+ throw new IllegalArgumentException("请选择正确的项目路径,或者还没有配置授权");
+ }
+ }
+ String logPath = projectInfo.logPath();
+ if (StrUtil.isNotEmpty(logPath)) {
+ if (!whitelistDirectoryService.checkProjectDirectory(logPath)) {
+ if (outGivingProject) {
+ whitelistDirectoryService.addProjectWhiteList(logPath);
+ } else {
+ throw new IllegalArgumentException("请填写的项目日志存储路径,或者还没有配置授权");
+ }
}
}
}
- }
- //
- String lib = projectInfo.getLib();
- Assert.state(StrUtil.isNotEmpty(lib) && !StrUtil.SLASH.equals(lib) && !Validator.isChinese(lib), "项目路径不能为空,不能为顶级目录,不能包含中文");
+ //
+ String lib = projectInfo.getLib();
+ Assert.state(StrUtil.isNotEmpty(lib) && !StrUtil.SLASH.equals(lib) && !Validator.isChinese(lib), "项目路径不能为空,不能为顶级目录,不能包含中文");
- FileUtils.checkSlip(lib, e -> new IllegalArgumentException("项目路径存在提升目录问题"));
- return projectInfoService.getItem(projectInfo.getId());
+ FileUtils.checkSlip(lib, e -> new IllegalArgumentException("项目路径存在提升目录问题"));
+ }
}
@@ -133,40 +141,22 @@ public class ManageEditProjectController extends BaseAgentController {
// 预检查数据
String strPreviewData = getParameter("previewData");
boolean previewData = Convert.toBool(strPreviewData, false);
- String whitelistDirectory = projectInfo.getWhitelistDirectory();
+
//
- NodeProjectInfoModel exits = this.checkParameter(projectInfo, whitelistDirectory, previewData);
- String id = projectInfo.getId();
- //
- String allLib = projectInfo.allLib();
- // 判断空格
- Assert.state(!id.contains(StrUtil.SPACE) && !allLib.contains(StrUtil.SPACE), "项目Id、项目路径不能包含空格");
- File checkFile = FileUtil.file(allLib);
- Assert.state(!FileUtil.exist(checkFile) || FileUtil.isDirectory(checkFile), "项目路径是一个已经存在的文件");
- // 重复lib
- List list = projectInfoService.list();
- if (list != null) {
- for (NodeProjectInfoModel nodeProjectInfoModel : list) {
- File fileLib = FileUtil.file(nodeProjectInfoModel.allLib());
- if (!nodeProjectInfoModel.getId().equals(id) && FileUtil.equals(fileLib, checkFile)) {
- return new JsonMessage<>(401, "当前项目路径已经被【" + nodeProjectInfoModel.getName() + "】占用,请检查");
- }
- }
- }
+ this.checkParameter(projectInfo, previewData);
+
// 自动生成log文件
- String log = projectInfo.getLog();
- Assert.hasText(log, "项目log解析读取失败");
- checkFile = FileUtil.file(log);
+ File checkFile = this.projectInfoService.resolveAbsoluteLogFile(projectInfo);
Assert.state(!FileUtil.exist(checkFile) || FileUtil.isFile(checkFile), "项目log是一个已经存在的文件夹");
//
- String token = projectInfo.getToken();
+ String token = projectInfo.token();
if (StrUtil.isNotEmpty(token)) {
Validator.validateMatchRegex(RegexPool.URL_HTTP, token, "WebHooks 地址不合法");
}
// 判断 yml
this.checkDslYml(projectInfo);
//
- return save(projectInfo, exits, previewData);
+ return this.save(projectInfo, previewData);
}
private void checkDslYml(NodeProjectInfoModel projectInfo) {
@@ -174,7 +164,7 @@ public class ManageEditProjectController extends BaseAgentController {
String dslContent = projectInfo.getDslContent();
Assert.hasText(dslContent, "请配置 dsl 内容");
DslYmlDto build = DslYmlDto.build(dslContent);
- Assert.state(build.hasRunProcess("status"), "没有配置 run.status");
+ Assert.state(build.hasRunProcess(ConsoleCommandOp.status.name()), "没有配置 run.status");
}
}
@@ -185,15 +175,16 @@ public class ManageEditProjectController extends BaseAgentController {
* @param previewData 是否是预检查
* @return 错误信息
*/
- private IJsonMessage save(NodeProjectInfoModel projectInfo, NodeProjectInfoModel exits, boolean previewData) {
- projectInfo.setWorkspaceId(getWorkspaceId());
-
+ private IJsonMessage save(NodeProjectInfoModel projectInfo, boolean previewData) {
this.checkPath(projectInfo);
+ //
+ NodeProjectInfoModel exits = projectInfoService.getItem(projectInfo.getId());
+ projectInfo.setWorkspaceId(this.getWorkspaceId());
RunMode runMode = projectInfo.getRunMode();
if (exits == null) {
// 检查运行中的tag 是否被占用
if (runMode != RunMode.File && runMode != RunMode.Dsl) {
- Assert.state(!AbstractProjectCommander.getInstance().isRun(projectInfo), "当前项目id已经被正在运行的程序占用");
+ Assert.state(!projectCommander.isRun(projectInfo), "当前项目id已经被正在运行的程序占用");
}
if (previewData) {
// 预检查数据
@@ -207,29 +198,34 @@ public class ManageEditProjectController extends BaseAgentController {
// 预检查数据
return JsonMessage.success("检查通过");
} else {
+ exits.setNodeId(projectInfo.getNodeId());
exits.setName(projectInfo.getName());
exits.setGroup(projectInfo.getGroup());
exits.setAutoStart(projectInfo.getAutoStart());
- exits.setMainClass(projectInfo.getMainClass());
+ exits.setMainClass(projectInfo.mainClass());
exits.setJvm(projectInfo.getJvm());
exits.setArgs(projectInfo.getArgs());
exits.setWorkspaceId(this.getWorkspaceId());
exits.setOutGivingProject(projectInfo.isOutGivingProject());
exits.setRunMode(runMode);
- exits.setToken(projectInfo.getToken());
+ exits.setToken(projectInfo.token());
exits.setDslContent(projectInfo.getDslContent());
exits.setDslEnv(projectInfo.getDslEnv());
-
- exits.setJavaExtDirsCp(projectInfo.getJavaExtDirsCp());
- // 移动到新路径
- this.moveTo(exits, projectInfo);
- // 最后才设置新的路径
- exits.setLib(projectInfo.getLib());
- exits.setWhitelistDirectory(projectInfo.getWhitelistDirectory());
- //
- exits.setLog(projectInfo.getLog());
- exits.setLogPath(projectInfo.getLogPath());
- projectInfoService.updateItem(exits);
+ exits.setJavaExtDirsCp(projectInfo.javaExtDirsCp());
+ if (runMode == RunMode.Link) {
+ // 如果是链接模式
+ Assert.state(runMode == exits.getRunMode(), "已经存在的项目不能修改为软链项目");
+ } else {
+ // 移动到新路径
+ this.moveTo(exits, projectInfo);
+ // 最后才设置新的路径
+ exits.setLib(projectInfo.getLib());
+ exits.setWhitelistDirectory(projectInfo.whitelistDirectory());
+ //
+ //exits.setLog(projectInfo.log());
+ exits.setLogPath(projectInfo.logPath());
+ }
+ projectInfoService.updateById(exits, exits.getId());
return JsonMessage.success("修改成功");
}
}
@@ -237,8 +233,8 @@ public class ManageEditProjectController extends BaseAgentController {
private void moveTo(NodeProjectInfoModel old, NodeProjectInfoModel news) {
{
// 移动目录
- File oldLib = FileUtil.file(old.allLib());
- File newLib = FileUtil.file(news.allLib());
+ File oldLib = projectInfoService.resolveLibFile(old);
+ File newLib = projectInfoService.resolveLibFile(news);
if (!FileUtil.equals(oldLib, newLib)) {
// 正在运行的项目不能修改路径
this.projectMustNotRun(old, "正在运行的项目不能修改路径");
@@ -249,8 +245,8 @@ public class ManageEditProjectController extends BaseAgentController {
}
{
// log
- File oldLog = FileUtil.file(old.getLog());
- File newLog = FileUtil.file(news.getLog());
+ File oldLog = projectInfoService.resolveAbsoluteLogFile(old);
+ File newLog = projectInfoService.resolveAbsoluteLogFile(news);
if (!FileUtil.equals(oldLog, newLog)) {
// 正在运行的项目不能修改路径
this.projectMustNotRun(old, "正在运行的项目不能修改路径");
@@ -259,9 +255,9 @@ public class ManageEditProjectController extends BaseAgentController {
FileUtil.move(oldLog, newLog, true);
}
// logBack
- File oldLogBack = old.getLogBack();
+ File oldLogBack = projectInfoService.resolveLogBack(old);
if (oldLogBack.exists()) {
- File logBack = news.getLogBack();
+ File logBack = projectInfoService.resolveLogBack(news);
FileUtils.tempMoveContent(oldLogBack, logBack);
}
}
@@ -269,7 +265,7 @@ public class ManageEditProjectController extends BaseAgentController {
}
private void projectMustNotRun(NodeProjectInfoModel projectInfoModel, String msg) {
- boolean run = AbstractProjectCommander.getInstance().isRun(projectInfoModel);
+ boolean run = projectCommander.isRun(projectInfoModel);
Assert.state(!run, msg);
}
@@ -279,15 +275,41 @@ public class ManageEditProjectController extends BaseAgentController {
* @param nodeProjectInfoModel 比较的项目
*/
private void checkPath(NodeProjectInfoModel nodeProjectInfoModel) {
- List nodeProjectInfoModelList = projectInfoService.list();
- if (nodeProjectInfoModelList == null) {
+ String id = nodeProjectInfoModel.getId();
+ Assert.state(!id.contains(StrUtil.SPACE), "项目Id不能包含空格");
+ RunMode runMode = nodeProjectInfoModel.getRunMode();
+ if (runMode == RunMode.Link) {
return;
}
+ List list = projectInfoService.list();
+ if (list == null) {
+ return;
+ }
+ //
+ String allLib = nodeProjectInfoModel.allLib();
+ // 判断空格
+ Assert.state(!allLib.contains(StrUtil.SPACE), "项目路径不能包含空格");
+ File checkFile = FileUtil.file(allLib);
+ Assert.state(!FileUtil.exist(checkFile) || FileUtil.isDirectory(checkFile), "项目路径是一个已经存在的文件");
+ // 重复lib
+ for (NodeProjectInfoModel item : list) {
+ if (item.getRunMode() == RunMode.Link) {
+ continue;
+ }
+ File fileLib = projectInfoService.resolveLibFile(item);
+ if (!nodeProjectInfoModel.getId().equals(id) && FileUtil.equals(fileLib, checkFile)) {
+ throw new IllegalArgumentException("当前项目路径已经被【" + item.getName() + "】占用,请检查");
+ }
+ }
+
NodeProjectInfoModel nodeProjectInfoModel1 = null;
- for (NodeProjectInfoModel model : nodeProjectInfoModelList) {
+ for (NodeProjectInfoModel model : list) {
+ if (model.getRunMode() == RunMode.Link) {
+ continue;
+ }
if (!model.getId().equals(nodeProjectInfoModel.getId())) {
- File file1 = new File(model.allLib());
- File file2 = new File(nodeProjectInfoModel.allLib());
+ File file1 = projectInfoService.resolveLibFile(model);
+ File file2 = projectInfoService.resolveLibFile(nodeProjectInfoModel);
if (FileUtil.pathEquals(file1, file2)) {
nodeProjectInfoModel1 = model;
break;
@@ -310,15 +332,23 @@ public class ManageEditProjectController extends BaseAgentController {
* @return json
*/
@RequestMapping(value = "deleteProject", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
- public IJsonMessage deleteProject(String thorough) {
+ public IJsonMessage deleteProject(String id, String thorough) {
NodeProjectInfoModel nodeProjectInfoModel = tryGetProjectInfoModel();
if (nodeProjectInfoModel == null) {
// 返回正常 200 状态码,考虑节点分发重复操作
return JsonMessage.success("项目不存在");
}
// 运行判断
- boolean run = AbstractProjectCommander.getInstance().isRun(nodeProjectInfoModel);
+ boolean run = projectCommander.isRun(nodeProjectInfoModel);
Assert.state(!run, "不能删除正在运行的项目");
+ // 判断是否被软链
+ List list = projectInfoService.list();
+ for (NodeProjectInfoModel projectInfoModel : list) {
+ if (nodeProjectInfoModel.getRunMode() != RunMode.Link) {
+ continue;
+ }
+ Assert.state(!StrUtil.equals(projectInfoModel.getLinkId(), id), "项目被" + projectInfoModel.getName() + "软链中");
+ }
this.thorough(thorough, nodeProjectInfoModel);
//
projectInfoService.deleteItem(nodeProjectInfoModel.getId());
@@ -337,24 +367,28 @@ public class ManageEditProjectController extends BaseAgentController {
if (StrUtil.isEmpty(thorough)) {
return;
}
- File logBack = nodeProjectInfoModel.getLogBack();
+ File logBack = this.projectInfoService.resolveLogBack(nodeProjectInfoModel);
boolean fastDel = CommandUtil.systemFastDel(logBack);
Assert.state(!fastDel, "删除日志文件失败:" + logBack.getAbsolutePath());
- File log = FileUtil.file(nodeProjectInfoModel.getAbsoluteLog());
+ File log = this.projectInfoService.resolveAbsoluteLogFile(nodeProjectInfoModel);
fastDel = CommandUtil.systemFastDel(log);
Assert.state(!fastDel, "删除日志文件失败:" + log.getAbsolutePath());
//
- File allLib = FileUtil.file(nodeProjectInfoModel.allLib());
- fastDel = CommandUtil.systemFastDel(allLib);
- Assert.state(!fastDel, "删除项目文件失败:" + allLib.getAbsolutePath());
+ if (nodeProjectInfoModel.getRunMode() != RunMode.Link) {
+ // 非软链项目才删除文件
+ File allLib = projectInfoService.resolveLibFile(nodeProjectInfoModel);
+ fastDel = CommandUtil.systemFastDel(allLib);
+ Assert.state(!fastDel, "删除项目文件失败:" + allLib.getAbsolutePath());
+ }
}
@RequestMapping(value = "releaseOutGiving", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
public IJsonMessage