作者 钟来

应用程序告警

  1 +package com.ruoyi.system.domain.sys;
  2 +
  3 +import java.util.Date;
  4 +import com.fasterxml.jackson.annotation.JsonFormat;
  5 +import com.ruoyi.common.annotation.Excel;
  6 +import com.ruoyi.common.annotation.PublicSQLConfig;
  7 +import org.apache.commons.lang3.builder.ToStringBuilder;
  8 +import org.apache.commons.lang3.builder.ToStringStyle;
  9 +import io.swagger.annotations.ApiModel;
  10 +import io.swagger.annotations.ApiModelProperty;
  11 +import com.ruoyi.common.tool.BaseEntity;
  12 +
  13 +/**
  14 + * 应用状态监控对象 sys_monitor_application
  15 + *
  16 + * @author zhonglai
  17 + * @date 2025-06-25
  18 + */
  19 +@ApiModel("应用状态监控")
  20 +public class SysMonitorApplication extends BaseEntity
  21 +{
  22 + @PublicSQLConfig(isSelect = false)
  23 + private static final long serialVersionUID = 1L;
  24 +
  25 + /** $column.columnComment */
  26 + private Integer id;
  27 +
  28 + /** 更新时间 */
  29 + @ApiModelProperty(value="更新时间")
  30 + @Excel(name = "更新时间", width = 30)
  31 + private String timestamp;
  32 +
  33 + /** 主机 */
  34 + @ApiModelProperty(value="主机")
  35 + @Excel(name = "主机")
  36 + private String hostname;
  37 +
  38 + /** 名称 */
  39 + @ApiModelProperty(value="名称")
  40 + @Excel(name = "名称")
  41 + private String name;
  42 +
  43 + /** 进程id */
  44 + @ApiModelProperty(value="进程id")
  45 + @Excel(name = "进程id")
  46 + private Integer pid;
  47 +
  48 + /** cpu使用情况 */
  49 + @ApiModelProperty(value="cpu使用情况")
  50 + @Excel(name = "cpu使用情况")
  51 + private String cpu;
  52 +
  53 + /** 内存使用情况 */
  54 + @ApiModelProperty(value="内存使用情况")
  55 + @Excel(name = "内存使用情况")
  56 + private String mem;
  57 +
  58 + /** 执行指令 */
  59 + @ApiModelProperty(value="执行指令")
  60 + @Excel(name = "执行指令")
  61 + private String cmd;
  62 +
  63 + /** 状态 */
  64 + @ApiModelProperty(value="状态")
  65 + @Excel(name = "状态")
  66 + private String status;
  67 +
  68 + @ApiModelProperty(value="远程ip")
  69 + @Excel(name = "远程ip")
  70 + private String remoteIp;
  71 +
  72 + @ApiModelProperty(value="app描述")
  73 + @Excel(name = "app描述")
  74 + private String appDescribe;
  75 +
  76 + public String getAppDescribe() {
  77 + return appDescribe;
  78 + }
  79 +
  80 + public void setAppDescribe(String appDescribe) {
  81 + this.appDescribe = appDescribe;
  82 + }
  83 +
  84 + public String getRemoteIp() {
  85 + return remoteIp;
  86 + }
  87 +
  88 + public void setRemoteIp(String remoteIp) {
  89 + this.remoteIp = remoteIp;
  90 + }
  91 +
  92 + public void setId(Integer id)
  93 + {
  94 + this.id = id;
  95 + }
  96 +
  97 + public Integer getId()
  98 + {
  99 + return id;
  100 + }
  101 + public void setTimestamp(String timestamp)
  102 + {
  103 + this.timestamp = timestamp;
  104 + }
  105 +
  106 + public String getTimestamp()
  107 + {
  108 + return timestamp;
  109 + }
  110 + public void setHostname(String hostname)
  111 + {
  112 + this.hostname = hostname;
  113 + }
  114 +
  115 + public String getHostname()
  116 + {
  117 + return hostname;
  118 + }
  119 + public void setName(String name)
  120 + {
  121 + this.name = name;
  122 + }
  123 +
  124 + public String getName()
  125 + {
  126 + return name;
  127 + }
  128 + public void setPid(Integer pid)
  129 + {
  130 + this.pid = pid;
  131 + }
  132 +
  133 + public Integer getPid()
  134 + {
  135 + return pid;
  136 + }
  137 + public void setCpu(String cpu)
  138 + {
  139 + this.cpu = cpu;
  140 + }
  141 +
  142 + public String getCpu()
  143 + {
  144 + return cpu;
  145 + }
  146 + public void setMem(String mem)
  147 + {
  148 + this.mem = mem;
  149 + }
  150 +
  151 + public String getMem()
  152 + {
  153 + return mem;
  154 + }
  155 + public void setCmd(String cmd)
  156 + {
  157 + this.cmd = cmd;
  158 + }
  159 +
  160 + public String getCmd()
  161 + {
  162 + return cmd;
  163 + }
  164 + public void setStatus(String status)
  165 + {
  166 + this.status = status;
  167 + }
  168 +
  169 + public String getStatus()
  170 + {
  171 + return status;
  172 + }
  173 +
  174 + @Override
  175 + public String toString() {
  176 + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
  177 + .append("id", getId())
  178 + .append("timestamp", getTimestamp())
  179 + .append("hostname", getHostname())
  180 + .append("name", getName())
  181 + .append("pid", getPid())
  182 + .append("cpu", getCpu())
  183 + .append("mem", getMem())
  184 + .append("cmd", getCmd())
  185 + .append("status", getStatus())
  186 + .toString();
  187 + }
  188 +}
  1 +package com.ruoyi.system.domain.sys;
  2 +
  3 +import java.util.Date;
  4 +import com.fasterxml.jackson.annotation.JsonFormat;
  5 +import com.ruoyi.common.annotation.PublicSQLConfig;
  6 +import org.apache.commons.lang3.builder.ToStringBuilder;
  7 +import org.apache.commons.lang3.builder.ToStringStyle;
  8 +import com.ruoyi.common.annotation.Excel;
  9 +import io.swagger.annotations.ApiModel;
  10 +import io.swagger.annotations.ApiModelProperty;
  11 +import com.ruoyi.common.tool.BaseEntity;
  12 +
  13 +/**
  14 + * 应用状态监控记录对象 sys_monitor_application_log
  15 + *
  16 + * @author zhonglai
  17 + * @date 2025-06-25
  18 + */
  19 +@ApiModel("应用状态监控记录")
  20 +public class SysMonitorApplicationLog extends BaseEntity
  21 +{
  22 + @PublicSQLConfig(isSelect = false)
  23 + private static final long serialVersionUID = 1L;
  24 +
  25 + /** $column.columnComment */
  26 + private Integer id;
  27 +
  28 + /** 更新时间 */
  29 + @ApiModelProperty(value="更新时间")
  30 + @Excel(name = "更新时间", width = 30)
  31 + private String timestamp;
  32 +
  33 + /** 进程id */
  34 + @ApiModelProperty(value="进程id")
  35 + @Excel(name = "进程id")
  36 + private Integer pid;
  37 +
  38 + /** cpu使用情况 */
  39 + @ApiModelProperty(value="cpu使用情况")
  40 + @Excel(name = "cpu使用情况")
  41 + private String cpu;
  42 +
  43 + /** 内存使用情况 */
  44 + @ApiModelProperty(value="内存使用情况")
  45 + @Excel(name = "内存使用情况")
  46 + private String mem;
  47 +
  48 + /** 状态 */
  49 + @ApiModelProperty(value="状态")
  50 + @Excel(name = "状态")
  51 + private String status;
  52 +
  53 + @ApiModelProperty(value="应用表id")
  54 + @Excel(name = "应用表id")
  55 + private Integer monitorApplicationId;
  56 +
  57 + public Integer getMonitorApplicationId() {
  58 + return monitorApplicationId;
  59 + }
  60 +
  61 + public void setMonitorApplicationId(Integer monitorApplicationId) {
  62 + this.monitorApplicationId = monitorApplicationId;
  63 + }
  64 +
  65 + public void setId(Integer id)
  66 + {
  67 + this.id = id;
  68 + }
  69 +
  70 + public Integer getId()
  71 + {
  72 + return id;
  73 + }
  74 + public void setTimestamp(String timestamp)
  75 + {
  76 + this.timestamp = timestamp;
  77 + }
  78 +
  79 + public String getTimestamp()
  80 + {
  81 + return timestamp;
  82 + }
  83 + public void setPid(Integer pid)
  84 + {
  85 + this.pid = pid;
  86 + }
  87 +
  88 + public Integer getPid()
  89 + {
  90 + return pid;
  91 + }
  92 + public void setCpu(String cpu)
  93 + {
  94 + this.cpu = cpu;
  95 + }
  96 +
  97 + public String getCpu()
  98 + {
  99 + return cpu;
  100 + }
  101 + public void setMem(String mem)
  102 + {
  103 + this.mem = mem;
  104 + }
  105 +
  106 + public String getMem()
  107 + {
  108 + return mem;
  109 + }
  110 + public void setStatus(String status)
  111 + {
  112 + this.status = status;
  113 + }
  114 +
  115 + public String getStatus()
  116 + {
  117 + return status;
  118 + }
  119 +
  120 + @Override
  121 + public String toString() {
  122 + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
  123 + .append("id", getId())
  124 + .append("timestamp", getTimestamp())
  125 + .append("monitorApplicationId", getMonitorApplicationId())
  126 + .append("pid", getPid())
  127 + .append("cpu", getCpu())
  128 + .append("mem", getMem())
  129 + .append("status", getStatus())
  130 + .toString();
  131 + }
  132 +}
@@ -5,6 +5,7 @@ import cn.hutool.http.HttpUtil; @@ -5,6 +5,7 @@ import cn.hutool.http.HttpUtil;
5 import com.alibaba.fastjson.JSONObject; 5 import com.alibaba.fastjson.JSONObject;
6 import com.google.gson.JsonObject; 6 import com.google.gson.JsonObject;
7 import com.ruoyi.common.utils.DateUtils; 7 import com.ruoyi.common.utils.DateUtils;
  8 +import com.ruoyi.system.domain.sys.SysMonitorApplication;
8 import com.ruoyi.system.domain.sys.SysMonitorServer; 9 import com.ruoyi.system.domain.sys.SysMonitorServer;
9 import com.zhonglai.luhui.dao.service.PublicService; 10 import com.zhonglai.luhui.dao.service.PublicService;
10 import org.springframework.beans.factory.annotation.Autowired; 11 import org.springframework.beans.factory.annotation.Autowired;
@@ -42,10 +43,10 @@ public class ServerAlarmTask { @@ -42,10 +43,10 @@ public class ServerAlarmTask {
42 stringBuffer.append("\n"); 43 stringBuffer.append("\n");
43 if(sms.getCpu_usage()>=cpu_usage) 44 if(sms.getCpu_usage()>=cpu_usage)
44 { 45 {
45 - stringBuffer.append("<font color=\"warning\">"); 46 +// stringBuffer.append("<font color=\"warning\">");
46 stringBuffer.append(">CPU使用率:"); 47 stringBuffer.append(">CPU使用率:");
47 stringBuffer.append(sms.getCpu_usage()/100+"%"); 48 stringBuffer.append(sms.getCpu_usage()/100+"%");
48 - stringBuffer.append("</font>"); 49 +// stringBuffer.append("</font>");
49 }else{ 50 }else{
50 stringBuffer.append(">CPU使用率:"); 51 stringBuffer.append(">CPU使用率:");
51 stringBuffer.append(sms.getCpu_usage()/100+"%"); 52 stringBuffer.append(sms.getCpu_usage()/100+"%");
@@ -54,10 +55,10 @@ public class ServerAlarmTask { @@ -54,10 +55,10 @@ public class ServerAlarmTask {
54 stringBuffer.append("\n"); 55 stringBuffer.append("\n");
55 if(sms.getMemory_usage()>=memory_usage) 56 if(sms.getMemory_usage()>=memory_usage)
56 { 57 {
57 - stringBuffer.append("<font color=\"warning\">"); 58 +// stringBuffer.append("<font color=\"warning\">");
58 stringBuffer.append(">内存使用率:"); 59 stringBuffer.append(">内存使用率:");
59 stringBuffer.append(sms.getMemory_usage()/100+"%"); 60 stringBuffer.append(sms.getMemory_usage()/100+"%");
60 - stringBuffer.append("</font>"); 61 +// stringBuffer.append("</font>");
61 }else{ 62 }else{
62 stringBuffer.append(">内存使用率:"); 63 stringBuffer.append(">内存使用率:");
63 stringBuffer.append(sms.getMemory_usage()/100+"%"); 64 stringBuffer.append(sms.getMemory_usage()/100+"%");
@@ -66,10 +67,10 @@ public class ServerAlarmTask { @@ -66,10 +67,10 @@ public class ServerAlarmTask {
66 stringBuffer.append("\n"); 67 stringBuffer.append("\n");
67 if(sms.getDisk_usage()>=disk_usage) 68 if(sms.getDisk_usage()>=disk_usage)
68 { 69 {
69 - stringBuffer.append("<font color=\"warning\">"); 70 +// stringBuffer.append("<font color=\"warning\">");
70 stringBuffer.append(">磁盘使用率:"); 71 stringBuffer.append(">磁盘使用率:");
71 stringBuffer.append(sms.getDisk_usage()/100+"%"); 72 stringBuffer.append(sms.getDisk_usage()/100+"%");
72 - stringBuffer.append("</font>"); 73 +// stringBuffer.append("</font>");
73 }else{ 74 }else{
74 stringBuffer.append(">磁盘使用率:"); 75 stringBuffer.append(">磁盘使用率:");
75 stringBuffer.append(sms.getDisk_usage()/100+"%"); 76 stringBuffer.append(sms.getDisk_usage()/100+"%");
@@ -79,10 +80,10 @@ public class ServerAlarmTask { @@ -79,10 +80,10 @@ public class ServerAlarmTask {
79 80
80 if (sms.getConnection_count()>=connection_count) 81 if (sms.getConnection_count()>=connection_count)
81 { 82 {
82 - stringBuffer.append("<font color=\"warning\">"); 83 +// stringBuffer.append("<font color=\"warning\">");
83 stringBuffer.append(">系统连接数:"); 84 stringBuffer.append(">系统连接数:");
84 stringBuffer.append(sms.getConnection_count()); 85 stringBuffer.append(sms.getConnection_count());
85 - stringBuffer.append("</font>"); 86 +// stringBuffer.append("</font>");
86 }else{ 87 }else{
87 stringBuffer.append(">系统连接数:"); 88 stringBuffer.append(">系统连接数:");
88 stringBuffer.append(sms.getConnection_count()); 89 stringBuffer.append(sms.getConnection_count());
@@ -96,26 +97,70 @@ public class ServerAlarmTask { @@ -96,26 +97,70 @@ public class ServerAlarmTask {
96 ips.append("'"); 97 ips.append("'");
97 } 98 }
98 JSONObject jsonObject = new JSONObject(); 99 JSONObject jsonObject = new JSONObject();
99 - jsonObject.put("msgtype","markdown"); 100 + jsonObject.put("msgtype","text");
100 JSONObject text = new JSONObject(); 101 JSONObject text = new JSONObject();
101 text.put("content",stringBuffer.toString()); 102 text.put("content",stringBuffer.toString());
102 text.put("mentioned_mobile_list",new String[]{"@all"}); 103 text.put("mentioned_mobile_list",new String[]{"@all"});
103 - jsonObject.put("markdown",text); 104 + jsonObject.put("text",text);
104 HttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=0c811725-6ee8-4bb5-b7de-378b6fa5b9b0",jsonObject.toJSONString()); 105 HttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=0c811725-6ee8-4bb5-b7de-378b6fa5b9b0",jsonObject.toJSONString());
105 106
106 publicService.updateBySql("update `sys_monitor_server` set notification_time="+DateUtils.getNowTimeMilly()+" where ip in("+ips+")"); 107 publicService.updateBySql("update `sys_monitor_server` set notification_time="+DateUtils.getNowTimeMilly()+" where ip in("+ips+")");
107 } 108 }
108 } 109 }
109 110
  111 + public void checkServerStatus() {
  112 + List<Map<String,Object>> list = publicService.getObjectListBySQL("SELECT * FROM `sys_monitor_application` WHERE `status`='not_running' AND notification_time < "+(DateUtils.getNowTimeMilly()-2*60*60));
  113 + if(null != list && list.size()!=0)
  114 + {
  115 + StringBuffer stringBuffer = new StringBuffer("**应用运维状态:**");
  116 + StringBuffer ips = new StringBuffer("0");
  117 + for (Map<String,Object> map:list)
  118 + {
  119 + SysMonitorApplication sms = BeanUtil.mapToBean(map, SysMonitorApplication.class,false,null);
  120 + stringBuffer.append("\n");
  121 + stringBuffer.append("\n");
  122 +
  123 + stringBuffer.append(">ip:");
  124 + stringBuffer.append(sms.getRemoteIp());
  125 +
  126 + stringBuffer.append("\n");
  127 +// stringBuffer.append("<font color=\"warning\">");
  128 + stringBuffer.append(">"+sms.getAppDescribe()+":");
  129 + stringBuffer.append(sms.getName());
  130 +// stringBuffer.append("</font>");
  131 + stringBuffer.append("\n");
  132 + stringBuffer.append(DateUtils.parseDateToStr("yyyy年MM月dd日HH时mm分ss秒",new Date()));
  133 +
  134 + stringBuffer.append("\n");
  135 +// stringBuffer.append("<font color=\"warning\">");
  136 + stringBuffer.append("程序被运行停止,请联系管理员查看");
  137 +// stringBuffer.append("</font>");
  138 + stringBuffer.append("\n");
  139 +
  140 + ips.append(",");
  141 + ips.append(sms.getId());
  142 + }
  143 + JSONObject jsonObject = new JSONObject();
  144 + jsonObject.put("msgtype","text");
  145 + JSONObject text = new JSONObject();
  146 + text.put("content",stringBuffer.toString());
  147 + text.put("mentioned_mobile_list",new String[]{"@all"});
  148 + jsonObject.put("text",text);
  149 + HttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=0c811725-6ee8-4bb5-b7de-378b6fa5b9b0",jsonObject.toJSONString());
  150 +
  151 + publicService.updateBySql("update `sys_monitor_application` set notification_time="+DateUtils.getNowTimeMilly()+" where id in("+ips+")");
  152 + }
  153 + }
  154 +
110 public static void main(String[] args) { 155 public static void main(String[] args) {
111 StringBuffer stringBuffer = new StringBuffer("颜色测试:"); 156 StringBuffer stringBuffer = new StringBuffer("颜色测试:");
112 stringBuffer.append("<font color=\"warning\">警告</font>"); 157 stringBuffer.append("<font color=\"warning\">警告</font>");
113 JSONObject jsonObject = new JSONObject(); 158 JSONObject jsonObject = new JSONObject();
114 - jsonObject.put("msgtype","markdown"); 159 + jsonObject.put("msgtype","text");
115 JSONObject text = new JSONObject(); 160 JSONObject text = new JSONObject();
116 text.put("content",stringBuffer.toString()); 161 text.put("content",stringBuffer.toString());
117 text.put("mentioned_mobile_list",new String[]{"@all"}); 162 text.put("mentioned_mobile_list",new String[]{"@all"});
118 - jsonObject.put("markdown",text); 163 + jsonObject.put("text",text);
119 String str = HttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=0c811725-6ee8-4bb5-b7de-378b6fa5b9b0",jsonObject.toJSONString()); 164 String str = HttpUtil.post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=0c811725-6ee8-4bb5-b7de-378b6fa5b9b0",jsonObject.toJSONString());
120 System.out.println(str); 165 System.out.println(str);
121 } 166 }
@@ -11,9 +11,12 @@ import com.ruoyi.common.utils.GsonConstructor; @@ -11,9 +11,12 @@ import com.ruoyi.common.utils.GsonConstructor;
11 import com.ruoyi.common.utils.ServletUtils; 11 import com.ruoyi.common.utils.ServletUtils;
12 import com.ruoyi.common.utils.ip.IpUtils; 12 import com.ruoyi.common.utils.ip.IpUtils;
13 import com.ruoyi.framework.web.domain.Server; 13 import com.ruoyi.framework.web.domain.Server;
  14 +import com.ruoyi.system.domain.sys.SysMonitorApplication;
  15 +import com.ruoyi.system.domain.sys.SysMonitorApplicationLog;
14 import com.ruoyi.system.domain.sys.SysMonitorServer; 16 import com.ruoyi.system.domain.sys.SysMonitorServer;
15 import com.ruoyi.system.domain.sys.SysMonitorServerLog; 17 import com.ruoyi.system.domain.sys.SysMonitorServerLog;
16 import com.zhonglai.luhui.action.BaseController; 18 import com.zhonglai.luhui.action.BaseController;
  19 +import com.zhonglai.luhui.admin.dto.MonitorServerUploadApplicationDto;
17 import com.zhonglai.luhui.admin.dto.MonitorServerUploadDto; 20 import com.zhonglai.luhui.admin.dto.MonitorServerUploadDto;
18 import com.zhonglai.luhui.admin.qywx.AesException; 21 import com.zhonglai.luhui.admin.qywx.AesException;
19 import com.zhonglai.luhui.admin.qywx.QyWxApplication; 22 import com.zhonglai.luhui.admin.qywx.QyWxApplication;
@@ -26,6 +29,7 @@ import io.swagger.annotations.ApiOperation; @@ -26,6 +29,7 @@ import io.swagger.annotations.ApiOperation;
26 import org.springframework.beans.factory.annotation.Autowired; 29 import org.springframework.beans.factory.annotation.Autowired;
27 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 30 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
28 import org.springframework.security.access.prepost.PreAuthorize; 31 import org.springframework.security.access.prepost.PreAuthorize;
  32 +import org.springframework.transaction.annotation.Transactional;
29 import org.springframework.util.StreamUtils; 33 import org.springframework.util.StreamUtils;
30 import org.springframework.web.bind.annotation.*; 34 import org.springframework.web.bind.annotation.*;
31 import org.w3c.dom.Document; 35 import org.w3c.dom.Document;
@@ -73,6 +77,7 @@ public class ServerController extends BaseController @@ -73,6 +77,7 @@ public class ServerController extends BaseController
73 } 77 }
74 78
75 @ApiOperation("上传状态") 79 @ApiOperation("上传状态")
  80 + @Transactional
76 @PostMapping("/upload") 81 @PostMapping("/upload")
77 public AjaxResult upload(@RequestBody MonitorServerUploadDto monitorServerUploadDto) 82 public AjaxResult upload(@RequestBody MonitorServerUploadDto monitorServerUploadDto)
78 { 83 {
@@ -84,12 +89,30 @@ public class ServerController extends BaseController @@ -84,12 +89,30 @@ public class ServerController extends BaseController
84 sysMonitorServer.setIp(ip+"("+monitorServerUploadDto.getLocalip()+")"); 89 sysMonitorServer.setIp(ip+"("+monitorServerUploadDto.getLocalip()+")");
85 } 90 }
86 Long st = publicService.getObjectListTotle(sysMonitorServer, null); 91 Long st = publicService.getObjectListTotle(sysMonitorServer, null);
87 - sysMonitorServer.setCpu_usage(new Double(monitorServerUploadDto.getCpu_usage()*100).intValue());  
88 - sysMonitorServer.setConnection_count(monitorServerUploadDto.getConnection_count());  
89 - sysMonitorServer.setMemory_usage(new Double(monitorServerUploadDto.getMemory_usage()*100).intValue());  
90 - sysMonitorServer.setDisk_usage(new Double(monitorServerUploadDto.getDisk_usage()*100).intValue());  
91 - sysMonitorServer.setCpu_info(tranPsAux(monitorServerUploadDto.getCpu_info()));  
92 - sysMonitorServer.setMemory_info(tranPsAux(monitorServerUploadDto.getMemory_info())); 92 + if(null != monitorServerUploadDto.getCpu_usage())
  93 + {
  94 + sysMonitorServer.setCpu_usage(new Double(monitorServerUploadDto.getCpu_usage()*100).intValue());
  95 + }
  96 + if(null != monitorServerUploadDto.getConnection_count())
  97 + {
  98 + sysMonitorServer.setConnection_count(monitorServerUploadDto.getConnection_count());
  99 + }
  100 + if(null != monitorServerUploadDto.getMemory_usage())
  101 + {
  102 + sysMonitorServer.setMemory_usage(new Double(monitorServerUploadDto.getMemory_usage()*100).intValue());
  103 + }
  104 + if(null != monitorServerUploadDto.getDisk_usage())
  105 + {
  106 + sysMonitorServer.setDisk_usage(new Double(monitorServerUploadDto.getDisk_usage()*100).intValue());
  107 + }
  108 + if (null != monitorServerUploadDto.getCpu_info())
  109 + {
  110 + sysMonitorServer.setCpu_info(tranPsAux(monitorServerUploadDto.getCpu_info()));
  111 + }
  112 + if (null != monitorServerUploadDto.getMemory_info())
  113 + {
  114 + sysMonitorServer.setMemory_info(tranPsAux(monitorServerUploadDto.getMemory_info()));
  115 + }
93 116
94 if(st==0) 117 if(st==0)
95 { 118 {
@@ -110,6 +133,48 @@ public class ServerController extends BaseController @@ -110,6 +133,48 @@ public class ServerController extends BaseController
110 return AjaxResult.success(); 133 return AjaxResult.success();
111 } 134 }
112 135
  136 + @ApiOperation("上传应用状态")
  137 + @Transactional
  138 + @PostMapping("/uploadApplication")
  139 + public AjaxResult uploadApplication(@RequestBody MonitorServerUploadApplicationDto monitorServerUploadApplicationDto)
  140 + {
  141 + String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
  142 +
  143 + for(SysMonitorApplication sysMonitorApplication:monitorServerUploadApplicationDto.getData())
  144 + {
  145 + SysMonitorApplication selectSysMonitorApplication = publicService.getObject(SysMonitorApplication.class,"remoteIp,name", ip+","+sysMonitorApplication.getName());
  146 + sysMonitorApplication.setRemoteIp(ip);
  147 + if(null == selectSysMonitorApplication)
  148 + {
  149 + publicService.insert(sysMonitorApplication);
  150 + }else {
  151 + sysMonitorApplication.setId(selectSysMonitorApplication.getId());
  152 + publicService.updateObject(sysMonitorApplication,"id");
  153 + }
  154 + SysMonitorApplicationLog sysMonitorApplicationLog = JSONObject.parseObject(JSONObject.toJSONString(sysMonitorApplication),SysMonitorApplicationLog.class);
  155 + sysMonitorApplicationLog.setId(null);
  156 + sysMonitorApplicationLog.setMonitorApplicationId(sysMonitorApplication.getId());
  157 + publicService.insert(sysMonitorApplicationLog);
  158 + }
  159 + return AjaxResult.success();
  160 + }
  161 + @ApiOperation("获取服务器应用列表")
  162 + @GetMapping("/getServiceAoolicationList")
  163 + public Map<String,Object> getServiceAoolicationList()
  164 + {
  165 + String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
  166 + List<Map<String,Object>> list = publicService.getObjectListBySQL("SELECT GROUP_CONCAT(`name`) processes FROM `sys_monitor_application` WHERE remote_ip='"+ip+"' GROUP BY remote_ip");
  167 + Map<String,Object> map = new HashMap<>();
  168 + map.put("processes","");
  169 + if(null != list && list.size()>0)
  170 + {
  171 + String pprocesses = list.get(0).get("processes").toString();
  172 + map.put("processes",pprocesses.split(","));
  173 + }
  174 + return map;
  175 + }
  176 +
  177 +
113 private String tranPsAux(String princmd) 178 private String tranPsAux(String princmd)
114 { 179 {
115 String[] auxs = princmd.split(";"); 180 String[] auxs = princmd.split(";");
@@ -211,6 +276,26 @@ public class ServerController extends BaseController @@ -211,6 +276,26 @@ public class ServerController extends BaseController
211 return getDataTable(list); 276 return getDataTable(list);
212 } 277 }
213 278
  279 + @ApiOperation("获取应用状态列表")
  280 + @GetMapping("/getSysMonitorApplicationList")
  281 + public TableDataInfo getSysMonitorApplicationList(SysMonitorApplication sysMonitorApplication) throws Exception
  282 + {
  283 + startPage();
  284 + startOrderBy();
  285 + List<Map<String,Object>> list = publicService.getObjectList(sysMonitorApplication,"*",null,null,0,0);
  286 + return getDataTable(list);
  287 + }
  288 +
  289 + @ApiOperation("获取应用状态记录列表")
  290 + @GetMapping("/getSysMonitorApplicationLogList")
  291 + public TableDataInfo getSysMonitorApplicationLogList(SysMonitorApplicationLog sysMonitorApplicationLog) throws Exception
  292 + {
  293 + startPage();
  294 + startOrderBy();
  295 + List<Map<String,Object>> list = publicService.getObjectList(sysMonitorApplicationLog,"*",null,null,0,0);
  296 + return getDataTable(list);
  297 + }
  298 +
214 @ApiOperation("获取服务器状态曲线") 299 @ApiOperation("获取服务器状态曲线")
215 @GetMapping("/getSysMonitorServerLogList") 300 @GetMapping("/getSysMonitorServerLogList")
216 public TableDataInfo getSysMonitorServerLogList(String ip,Long startTime,Long endTime) throws Exception 301 public TableDataInfo getSysMonitorServerLogList(String ip,Long startTime,Long endTime) throws Exception
@@ -233,4 +318,10 @@ public class ServerController extends BaseController @@ -233,4 +318,10 @@ public class ServerController extends BaseController
233 SysMonitorServerLog sysMonitorServerLog = publicService.getObject(SysMonitorServerLog.class,"id",id+""); 318 SysMonitorServerLog sysMonitorServerLog = publicService.getObject(SysMonitorServerLog.class,"id",id+"");
234 return AjaxResult.success(sysMonitorServerLog); 319 return AjaxResult.success(sysMonitorServerLog);
235 } 320 }
  321 +
  322 + public static void main(String[] args) {
  323 + String str = "{\"data\":[ {\"timestamp\":\"2025-06-25 22:07:01\",\"hostname\":\"iZ28dmbj1ksZ\",\"name\":\"lh-admin.jar\",\"pid\":5603,\"cpu\":3.3,\"mem\":8.2,\"cmd\":\"/root/jdk1.8.0_291/bin/java -jar -Xmx1024M -Xms256M /www/wwwroot/lh-admin/lh-admin.jar --server.port\u003d6257 --spring.config.location\u003d/www/wwwroot/lh-admin/application.yml\",\"status\":\"running\"},{\"timestamp\":\"2025-06-25 22:07:01\",\"hostname\":\"iZ28dmbj1ksZ\",\"name\":\"ly-zhongyu-device-service.jar\",\"pid\":16942,\"cpu\":0.0,\"mem\":0.0,\"cmd\":\"curl -X POST -H Content-Type: application/json -d {\"cpu_usage\": \"66.7\", \"memory_usage\": \"70.85\", \"disk_usage\": \"61\", \"connection_count\": \"105\", \"memory_info\": \"USERfg9527PIDfg9527MEMORY(M)fg9527COMMAND;mysqlfg952715047fg95272665.56Mfg9527/www/server/mysql/bin/mysqld --basedir\u003d/www/server/mysql --datadir\u003d/www/server/data --plugin-dir\u003d/www/server/mysql/lib/plugin --user\u003dmysql --log-error\u003diZ28dmbj1ksZ.err --open-files-limit\u003d65535 --pid-file\u003d/www/server/data/iZ28dmbj1ksZ.pid --socket\u003d/tmp/mysql.sock --port\u003d3306 ;rootfg95275603fg9527648.18Mfg9527/root/jdk1.8.0_291/bin/java -jar -Xmx1024M -Xms256M /www/wwwroot/lh-admin/lh-admin.jar --server.port\u003d6257 --spring.config.location\u003d/www/wwwroot/lh-admin/application.yml ;gitfg952716053fg9527379.48Mfg9527sidekiq 4.1.2 gitlab-rails [0 of 25 busy] ;gitfg952731125fg9527317.29Mfg9527unicorn worker[1] -D -E production -c /var/opt/gitlab/gitlab-rails/etc/unicorn.rb /opt/gitlab/embedded/service/gitlab-rails/config.ru ;gitfg952718271fg9527316.69Mfg9527unicorn worker[2] -D -E production -c /var/opt/gitlab/gitlab-rails/etc/unicorn.rb /opt/gitlab/embedded/service/gitlab-rails/config.ru ;gitfg952716299fg9527315.64Mfg9527unicorn worker[0] -D -E production -c /var/opt/gitlab/gitlab-rails/etc/unicorn.rb /opt/gitlab/embedded/service/gitlab-rails/config.ru ;rootfg952731718fg9527302.00Mfg9527/root/jdk1.8.0_291/bin/java -jar -Xmx512M -Xms256M /www/wwwroot/ly-zhongyu-device-service/ly-zhongyu-device-service.jar --server.port\u003d7624 ;gitfg952716109fg9527265.38Mfg9527unicorn master -D -E production -c /var/opt/gitlab/gitlab-rails/etc/unicorn.rb /opt/gitlab/embedded/service/gitlab-rails/config.ru ;gitlab-+fg952716056fg952768.73Mfg9527/opt/gitlab/embedded/bin/postgres -D /var/opt/gitlab/postgresql/data ;rootfg952728865fg952768.66Mfg9527/www/server/panel/pyenv/bin/python3 /www/server/panel/BT-Panel ;\", \"cpu_info\": \"USERfg9527PIDfg9527CPU(%)fg9527COMMAND;rootfg952732008fg95273.40%fg9527/usr/local/aegis/aegis_client/aegis_12_53/AliYunDunMonitor ;rootfg95275603fg95273.30%fg9527/root/jdk1.8.0_291/bin/java -jar -Xmx1024M -Xms256M /www/wwwroot/lh-admin/lh-admin.jar --server.port\u003d6257 --spring.config.location\u003d/www/wwwroot/lh-admin/application.yml ;rootfg952731830fg95271.00%fg9527/usr/local/aegis/aegis_client/aegis_12_53/AliYunDun ;gitfg952716299fg95270.60%fg9527unicorn worker[0] -D -E production -c /var/opt/gitlab/gitlab-rails/etc/unicorn.rb /opt/gitlab/embedded/service/gitlab-rails/config.ru ;gitfg952718271fg95270.60%fg9527unicorn worker[2] -D -E production -c /var/opt/gitlab/gitlab-rails/etc/unicorn.rb /opt/gitlab/embedded/service/gitlab-rails/config.ru ;gitfg952731125fg95270.60%fg9527unicorn worker[1] -D -E production -c /var/opt/gitlab/gitlab-rails/etc/unicorn.rb /opt/gitlab/embedded/service/gitlab-rails/config.ru ;gitfg952716053fg95270.50%fg9527sidekiq 4.1.2 gitlab-rails [0 of 25 busy] ;rootfg952731718fg95270.20%fg9527/root/jdk1.8.0_291/bin/java -jar -Xmx512M -Xms256M /www/wwwroot/ly-zhongyu-device-service/ly-zhongyu-device-service.jar --server.port\u003d7624 ;rootfg95279fg95270.10%fg9527[rcu_sched] ;mysqlfg952715047fg95270.10%fg9527/www/server/mysql/bin/mysqld --basedir\u003d/www/server/mysql --datadir\u003d/www/server/data --plugin-dir\u003d/www/server/mysql/lib/plugin --user\u003dmysql --log-error\u003diZ28dmbj1ksZ.err --open-files-limit\u003d65535 --pid-file\u003d/www/server/data/iZ28dmbj1ksZ.pid --socket\u003d/tmp/mysql.sock --port\u003d3306 ;\"} --insecure https://lh.admin.yu2le.com/api/monitor/server/upload\",\"status\":\"running\"},{\"timestamp\":\"2025-06-25 22:07:01\",\"hostname\":\"iZ28dmbj1ksZ\",\"name\":\"ly-zhongyu-device-service.jar\",\"pid\":31718,\"cpu\":0.2,\"mem\":3.8,\"cmd\":\"/root/jdk1.8.0_291/bin/java -jar -Xmx512M -Xms256M /www/wwwroot/ly-zhongyu-device-service/ly-zhongyu-device-service.jar --server.port\u003d7624\",\"status\":\"running\"} ]}";
  324 +
  325 + System.out.println(JSONObject.parse(str));
  326 + }
236 } 327 }
  1 +package com.zhonglai.luhui.admin.dto;
  2 +
  3 +import com.ruoyi.system.domain.sys.SysMonitorApplication;
  4 +import io.swagger.annotations.ApiModel;
  5 +
  6 +import java.util.List;
  7 +
  8 +@ApiModel("服务器应用状态监控")
  9 +public class MonitorServerUploadApplicationDto {
  10 + private List<SysMonitorApplication> data;
  11 +
  12 + public List<SysMonitorApplication> getData() {
  13 + return data;
  14 + }
  15 +
  16 + public void setData(List<SysMonitorApplication> data) {
  17 + this.data = data;
  18 + }
  19 +}
  1 +#!/bin/bash
  2 +
  3 +# 安装(指定间隔) curl -sSL https://lh.admin.yu2le.com/shell/install_monitor_timer.sh | bash -s -- 1
  4 +# 卸载 curl -sSL https://yourserver.com/monitor/install_monitor_timer.sh | bash -s -- --uninstall
  5 +
  6 +# === 配置项 ===
  7 +SCRIPT_NAME="multi_process_monitor.sh"
  8 +SCRIPT_URL="https://lh.admin.yu2le.com/shell/$SCRIPT_NAME"
  9 +SCRIPT_TARGET_PATH="/usr/local/bin/$SCRIPT_NAME"
  10 +LOG_FILE="/var/log/multi_process_monitor.log"
  11 +
  12 +# === 处理参数 ===
  13 +if [[ "$1" == "--uninstall" ]]; then
  14 + echo "🗑️ 开始卸载..."
  15 +
  16 + # 删除 crontab 中的定时任务
  17 + crontab -l 2>/dev/null | grep -v "$SCRIPT_TARGET_PATH" | crontab -
  18 +
  19 + # 删除脚本文件
  20 + if [ -f "$SCRIPT_TARGET_PATH" ]; then
  21 + rm -f "$SCRIPT_TARGET_PATH"
  22 + echo "✅ 已删除脚本:$SCRIPT_TARGET_PATH"
  23 + fi
  24 +
  25 + echo "✅ 定时任务卸载完成。"
  26 + exit 0
  27 +fi
  28 +
  29 +# === 安装模式 ===
  30 +INTERVAL_MINUTES=$1
  31 +
  32 +# 默认每 5 分钟运行一次
  33 +if [[ -z "$INTERVAL_MINUTES" ]]; then
  34 + INTERVAL_MINUTES=5
  35 +fi
  36 +
  37 +# 参数校验
  38 +if ! [[ "$INTERVAL_MINUTES" =~ ^[1-9][0-9]*$ ]]; then
  39 + echo "❌ 错误:间隔时间必须是正整数分钟"
  40 + exit 1
  41 +fi
  42 +
  43 +echo "📥 正在安装 $SCRIPT_NAME,每 $INTERVAL_MINUTES 分钟执行一次"
  44 +
  45 +# 下载脚本
  46 +curl -fsSL "$SCRIPT_URL" -o "$SCRIPT_TARGET_PATH"
  47 +if [ $? -ne 0 ]; then
  48 + echo "❌ 脚本下载失败:$SCRIPT_URL"
  49 + exit 1
  50 +fi
  51 +chmod +x "$SCRIPT_TARGET_PATH"
  52 +
  53 +# 添加 crontab 任务
  54 +CRON_JOB="*/$INTERVAL_MINUTES * * * * $SCRIPT_TARGET_PATH >> $LOG_FILE 2>&1"
  55 +(crontab -l 2>/dev/null | grep -F "$SCRIPT_TARGET_PATH") >/dev/null
  56 +if [ $? -eq 0 ]; then
  57 + echo "✅ 定时任务已存在,无需添加"
  58 +else
  59 + (crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab -
  60 + echo "✅ 已添加定时任务"
  61 +fi
  62 +
  63 +echo "🟢 安装完成!日志文件:$LOG_FILE"
  1 +#!/bin/bash
  2 +
  3 +PROCESS_API="https://lh.admin.yu2le.com/api/monitor/server/getServiceAoolicationList"
  4 +UPLOAD_API="https://lh.admin.yu2le.com/api/monitor/server/uploadApplication"
  5 +
  6 +TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
  7 +HOSTNAME=$(hostname)
  8 +DATA_LIST=()
  9 +
  10 +# ✅ JSON 字符串转义函数
  11 +escape_json_string() {
  12 + echo "$1" | sed \
  13 + -e 's/\\/\\\\/g' \
  14 + -e 's/"/\\"/g' \
  15 + -e 's/\t/\\t/g' \
  16 + -e 's/\r/\\r/g' \
  17 + -e 's/\n/\\n/g'
  18 +}
  19 +
  20 +# 获取 process 名称列表
  21 +PROCESS_NAMES=$(curl -s "$PROCESS_API" | grep -oP '"processes"\s*:\s*\[\K[^\]]*' | tr -d '"' | tr ',' '\n')
  22 +
  23 +for NAME in $PROCESS_NAMES; do
  24 + MATCHED=false
  25 +
  26 + for PID in $(pgrep -f "$NAME"); do
  27 + MATCHED=true
  28 + STATS=$(ps -p $PID -o pid,%cpu,%mem,cmd --no-headers)
  29 + CPU=$(echo $STATS | awk '{print $2}')
  30 + MEM=$(echo $STATS | awk '{print $3}')
  31 + CMD=$(echo $STATS | cut -d ' ' -f4-)
  32 +
  33 + # 转义所有字段
  34 + ESC_CMD=$(escape_json_string "$CMD")
  35 + ESC_NAME=$(escape_json_string "$NAME")
  36 +
  37 + JSON="{\"timestamp\":\"$TIMESTAMP\",\"hostname\":\"$HOSTNAME\",\"name\":\"$ESC_NAME\",\"pid\":$PID,\"cpu\":$CPU,\"mem\":$MEM,\"cmd\":\"$ESC_CMD\",\"status\":\"running\"}"
  38 + DATA_LIST+=("$JSON")
  39 + done
  40 +
  41 + if [ "$MATCHED" = false ]; then
  42 + ESC_NAME=$(escape_json_string "$NAME")
  43 + JSON="{\"timestamp\":\"$TIMESTAMP\",\"hostname\":\"$HOSTNAME\",\"name\":\"$ESC_NAME\",\"status\":\"not_running\"}"
  44 + DATA_LIST+=("$JSON")
  45 + fi
  46 +done
  47 +
  48 +# 构造并上传 JSON
  49 +if [ ${#DATA_LIST[@]} -gt 0 ]; then
  50 + JOINED_JSON=""
  51 + for item in "${DATA_LIST[@]}"; do
  52 + if [ -n "$JOINED_JSON" ]; then
  53 + JOINED_JSON+=","
  54 + fi
  55 + JOINED_JSON+="$item"
  56 + done
  57 +
  58 + POST_BODY="{\"data\":[ $JOINED_JSON ]}"
  59 +
  60 + curl -s -X POST "$UPLOAD_API" \
  61 + -H "Content-Type: application/json" \
  62 + -d "$POST_BODY"
  63 +fi