提交 4de9d50a authored 作者: wangqiang's avatar wangqiang

采集程序、硬件检测程序、软件检测程序与远程桌面程序集成为一个安装包

上级 2294e1a6
......@@ -139,6 +139,13 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.priusis</groupId>
<artifactId>apq-pc-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
......
package com.priusis.client.extensions.http;
import com.fasterxml.jackson.databind.JsonNode;
import com.priusis.client.data.kv.KvEntry;
import com.priusis.client.extensions.ExtensionUpdate;
import com.priusis.client.extensions.http.conf.HttpConfiguration;
......
......@@ -3,8 +3,6 @@ package com.priusis.client.service;
import com.google.common.collect.Lists;
import com.priusis.client.service.conf.PcConnectionConfiguration;
import com.priusis.client.service.conf.PcPersistenceConfiguration;
import com.priusis.client.service.core.MqttService;
import com.priusis.client.service.core.MqttServiceImpl;
import com.priusis.monitor.mqtt.MqttClient;
import com.priusis.monitor.mqtt.MqttConnectResult;
import com.priusis.monitor.mqtt.MqttHandler;
......
apq:
iot-gateway: 10.2.68.40:7033
job:
type: all
PC_HOST: 10.2.68.40
vnc-repeater: 10.2.68.41:5500
\ No newline at end of file
......@@ -16,9 +16,9 @@
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${pkg.logFolder}/${pkg.name}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<maxFileSize>10MB</maxFileSize>
<maxHistory>3</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
......
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.priusis</groupId>
<artifactId>apq-pc-common</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<spring-boot.version>2.4.10</spring-boot.version>
<jna.version>3.0.9</jna.version>
<pkg.user>priusis-iot</pkg.user>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.11</version>
</dependency>
<dependency>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
<version>${jna.version}</version>
</dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
\ No newline at end of file
package com.priusis.job;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.priusis.dto.HwPortControllerDto;
import com.priusis.utils.IHwPortController;
import com.priusis.vo.MqttRpcDataMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Slf4j
@Component
@ConditionalOnExpression("'${apq.job.type:null}'=='all' || '${apq.job.type:null}'=='control'")
public class ApqControlJob {
// 一分钟一次上报
private final Long FIXED_DELAY = 60000L;
@Autowired
private RestTemplate restTemplate;
@Scheduled(fixedDelay = 60000L)
protected void controlProgramTask() {
log.info("硬件监控上报=================");
// todo
//testUsb();
// 获取硬件监控配置 params == data
ResponseEntity<MqttRpcDataMessage> forEntity = null;
try {
forEntity = restTemplate.getForEntity("http://localhost:8765/rpc_cmd/controll", MqttRpcDataMessage.class);
} catch (Exception e) {
log.error("硬件监控上报异常", e.getMessage());
}
if (null != forEntity) {
MqttRpcDataMessage body = forEntity.getBody();
String params = body.getParams();
if (StrUtil.isNotBlank(params)) {
Long sendTime = body.getSendTime();
long current = System.currentTimeMillis();
List<HwPortControllerDto> hwPortControllerDtos = JSONUtil.toList(params, HwPortControllerDto.class);
// 初始化硬件接口管理模块
int result = IHwPortController.instanceDll.APQ_HWPORT_Initialize();
log.info("APQ_HWPORT_Initialize ret:{}", result);
if (current - sendTime <= FIXED_DELAY && CollUtil.isNotEmpty(hwPortControllerDtos)) {
// 收到硬件策略下发请求
log.info("收到硬件策略下发请求, sendTime:{}, params:{}", sendTime, params);
for (HwPortControllerDto hwPortControllerDto : hwPortControllerDtos) {
HwPortControllerDto.DeviceHardwareEnum deviceHardwareEnum = hwPortControllerDto.getKey();
int doType = hwPortControllerDto.getDoType();
int limitType = hwPortControllerDto.getLimitType();
int value = hwPortControllerDto.getValue();
List<Integer> hwDeviceIds = deviceHardwareEnum.getHwDeviceIds();
String hwDeviceName = deviceHardwareEnum.getName();
// 设置普通设备权限
if (Objects.equals(deviceHardwareEnum.getHwGroup(), "Normal")) {
// 1F/2T
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
int result32 = IHwPortController.instanceDll.APQ_HWPORT_set_normal_device_permit(hwDeviceId, perm, null);
log.info("APQ_HWPORT_set_normal_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result32);
}
} else if (Objects.equals(deviceHardwareEnum.getHwGroup(), "Storage")) { // 设置存储设备权限
// 1F/2T/3T-ALL/4T-R/5T-CI/6T-CO 拷出目前无用!! Storage移动硬盘,TYPEC 无效 !!
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
if (perm == 2) {
// limitType 1读写 2只读 3拷入 4拷出 5不限速 6限速
perm = (limitType == 1 ? 3 : limitType == 2 ? 4 : limitType == 3 ? 5 : limitType == 4 ? 6 : 3);
}
int result32 = IHwPortController.instanceDll.APQ_HWPORT_set_storage_device_permit(hwDeviceId, perm, null);
log.info("APQ_HWPORT_set_storage_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result32);
}
} else if (Objects.equals(deviceHardwareEnum.getHwGroup(), "NET")) { // 设置网络设备权限
// 1F/2T/3T-NS/4T-S-200 网口,4G/5G模块,无线WIFI区分不了 !!
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
if (perm == 2) {
// limitType 1读写 2只读 3拷入 4拷出 5不限速 6限速
perm = (limitType == 5 ? 3 : limitType == 6 ? 4 : 2);
}
int result32 = IHwPortController.instanceDll.APQ_HWPORT_set_net_device_permit(hwDeviceId, perm, value, null);
log.info("APQ_HWPORT_set_net_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result32);
}
}
// 应用硬件接口管理模块的配置内容
int result5 = IHwPortController.instanceDll.APQ_HWPORT_Apply();
log.info("APQ_HWPORT_Apply ret:{}", result5);
}
} else {
log.info("执行硬件监控, sendTime:{}, params:{}", sendTime, params);
// 上报硬件监控数据
Map mapRequest = new HashMap();
for (HwPortControllerDto hwPortControllerDto : hwPortControllerDtos) {
HwPortControllerDto.DeviceHardwareEnum deviceHardwareEnum = hwPortControllerDto.getKey();
int doType = hwPortControllerDto.getDoType();
int limitType = hwPortControllerDto.getLimitType();
int value = hwPortControllerDto.getValue();
List<Integer> hwDeviceIds = deviceHardwareEnum.getHwDeviceIds();
String hwDeviceName = deviceHardwareEnum.getName();
// 设置普通设备权限
if (Objects.equals(deviceHardwareEnum.getHwGroup(), "Normal")) {
// 1F/2T
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
if (perm == 1) {
// 获取普通设备权限
int result31 = IHwPortController.instanceDll.APQ_HWPORT_get_normal_device_permit(hwDeviceId);
log.debug("APQ_HWPORT_get_normal_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result31);
if (result31 == 2) {
mapRequest.put(deviceHardwareEnum.name(), perm);
}
}
}
} else if (Objects.equals(deviceHardwareEnum.getHwGroup(), "Storage")) { // 设置存储设备权限
// 1F/2T/3T-ALL/4T-R/5T-CI/6T-CO 拷出目前无用!! Storage移动硬盘,TYPEC 无效 !!
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
if (perm == 2) {
// limitType 1读写 2只读 3拷入 4拷出 5不限速 6限速
perm = (limitType == 1 ? 3 : limitType == 2 ? 4 : limitType == 3 ? 5 : limitType == 4 ? 6 : 3);
}
int result32 = IHwPortController.instanceDll.APQ_HWPORT_get_storage_device_permit(hwDeviceId);
log.info("APQ_HWPORT_get_storage_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result32);
if (perm != result32) {
mapRequest.put(deviceHardwareEnum.name(), perm);
}
}
} else if (Objects.equals(deviceHardwareEnum.getHwGroup(), "NET")) { // 设置网络设备权限
// 1F/2T/3T-NS/4T-S-200 网口,4G/5G模块,无线WIFI区分不了 !!
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
if (perm == 2) {
// limitType 1读写 2只读 3拷入 4拷出 5不限速 6限速
perm = (limitType == 5 ? 3 : limitType == 6 ? 4 : 2);
}
int result32 = IHwPortController.instanceDll.APQ_HWPORT_get_net_device_permit(hwDeviceId, 0);
log.info("APQ_HWPORT_get_net_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result32);
if (perm != result32) {
mapRequest.put(deviceHardwareEnum.name(), perm);
}
}
}
}
if (mapRequest.size() > 0) {
Map eventMapRequest = new HashMap();
eventMapRequest.put("methodName", "control_warning");
eventMapRequest.put("params", mapRequest);
Map map = restTemplate.postForObject("http://localhost:8765/uplink_event/oc-client", eventMapRequest, Map.class);
log.info("存在硬件接口扫码告警,上报告警事件: mapData:{}, ret:{}", mapRequest, map);
}
}
// 清理硬件接口管理模块
int result2 = IHwPortController.instanceDll.APQ_HWPORT_Uninitialize();
log.info("APQ_HWPORT_Uninitialize ret:{}", result2);
} else {
log.info("未获取到获取硬件监控配置");
}
} else {
log.info("未获取到获取硬件监控配置");
//int result = IHwPortController.instanceDll.APQ_HWPORT_Initialize();
//log.info("APQ_HWPORT_Initialize ret:{}", result);
//int result2 = IHwPortController.instanceDll.APQ_HWPORT_Uninitialize();
//log.info("APQ_HWPORT_Uninitialize ret:{}", result2);
}
}
public void testUsb() {
// 初始化硬件接口管理模块
int result = IHwPortController.instanceDll.APQ_HWPORT_Initialize();
log.info("APQ_HWPORT_Initialize ret:{}", result);
// APQ_HWPORT_STORAGE_PERM_ALLOW APQ_HWPORT_STORAGE_PERM_DENY
int result32 = IHwPortController.instanceDll.APQ_HWPORT_set_storage_device_permit(IHwPortController.HwportStorageDevidEnum.APQ_HWPORT_STORAGE_DEVID_UDISK.getCode(), IHwPortController.HwportStoragePermEnum.APQ_HWPORT_STORAGE_PERM_ALLOW.getCode(), null);
log.info("APQ_HWPORT_set_storage_device_permit ret:{}", result32);
//应用硬件接口管理模块的配置内容
int result5 = IHwPortController.instanceDll.APQ_HWPORT_Apply();
log.info("APQ_HWPORT_Apply ret:{}", result5);
int result2 = IHwPortController.instanceDll.APQ_HWPORT_Uninitialize();
log.info("APQ_HWPORT_Uninitialize ret:{}", result2);
}
}
package com.priusis.job;
import cn.hutool.core.io.unit.DataSizeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.system.oshi.CpuInfo;
import cn.hutool.system.oshi.OshiUtil;
import com.priusis.utils.MacAddrUtil;
import com.priusis.vo.ApqInfoDataVo;
import com.priusis.vo.MqttRpcDataMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HWPartition;
import oshi.util.FormatUtil;
import java.io.File;
import java.net.InetAddress;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@Component
@ConditionalOnExpression("'${apq.job.type:null}'=='all' || '${apq.job.type:null}'=='info'")
public class ApqInfoJob {
@Autowired
private RestTemplate restTemplate;
private int runningIndex = 0;
// 30秒一次上报
@Scheduled(fixedDelay = 30000L)
protected void controlProgramTask() {
log.info("设备实时数据采集上报=================");
runningIndex++;
boolean isNoneEven = runningIndex % 2 == 0;
// 获取采集配置,数据上报频率 params == data
ResponseEntity<MqttRpcDataMessage> forEntity = null;
Map<String, Integer> mapParams = null;
try {
forEntity = restTemplate.getForEntity("http://localhost:8765/rpc_cmd/info", MqttRpcDataMessage.class);
if (null != forEntity) {
MqttRpcDataMessage body = forEntity.getBody();
String params = body.getParams();
if (StrUtil.isNotBlank(params)) {
List<ApqInfoDataVo> apqInfoDataVos = JSONUtil.toList(params, ApqInfoDataVo.class);
mapParams = new HashMap<>();
for (ApqInfoDataVo apqInfoDataVo : apqInfoDataVos) {
mapParams.put(apqInfoDataVo.getCode(), apqInfoDataVo.getFrequency());
}
}
}
} catch (Exception e) {
log.error("采集数据异常", e);
}
String operatingSystem = "operatingSystem";
String mac = "mac";
String baseboard = "baseboard";
String ip = "ip";
String cpuModel = "cpuModel";
String cpuLoad = "cpuLoad";
String cpuTemp = "cpuTemp";
String memoryCap = "memoryCap";
String memoryAvailable = "memoryAvailable";
String diskModel = "diskModel";
String diskCap = "diskCap";
String diskFree = "diskFree";
try {
// 上报PC实时信息
String collect = null;
String collect1 = null;
String collect2 = null;
try {
collect = Arrays.stream(OshiUtil.getHardware().getDiskStores())
.map(HWDiskStore::getPartitions)
.flatMap(Arrays::stream)
.filter(partition -> StrUtil.isNotBlank(partition.getMountPoint()))
.map(partition -> "\"" + StrUtil.removeSuffix(partition.getMountPoint(), ":\\") + "盘\":\"" +
DataSizeUtil.format(partition.getSize()) + "\"")
.collect(Collectors.joining(",", "{", "}"));
collect1 = Arrays.stream(OshiUtil.getHardware().getDiskStores())
.map(store -> Arrays.stream(store.getPartitions())
.map(HWPartition::getMountPoint)
.filter(StrUtil::isNotBlank)
.map(s -> "\"" + StrUtil.removeSuffix(s, ":\\") + "盘\":\"" +
StrUtil.removeSuffix(store.getModel(), " (标准磁盘驱动器)") + "\"")
.collect(Collectors.joining(",")))
.filter(StrUtil::isNotBlank)
.collect(Collectors.joining(",", "{", "}"));
collect2 = Arrays.stream(OshiUtil.getHardware().getDiskStores())
.map(HWDiskStore::getPartitions)
.flatMap(Arrays::stream)
.filter(partition -> StrUtil.isNotBlank(partition.getMountPoint()))
.map(partition -> "\"" + StrUtil.removeSuffix(partition.getMountPoint(), ":\\") + "盘\":\"" +
new DecimalFormat("#.00").format(100d * new File(partition.getMountPoint()).getFreeSpace() / partition.getSize()) + "%\"")
.collect(Collectors.joining(",", "{", "}"));
} catch (Exception e) {
log.error("硬盘数据获取失败", e);
}
Map<String, Object> data = MapUtil.<String, Object>builder()
.put(isNeedCollection(isNoneEven, operatingSystem, mapParams), operatingSystem, OshiUtil.getOs().toString())
.put(isNeedCollection(isNoneEven, mac, mapParams), mac, MacAddrUtil.get())
.put(isNeedCollection(isNoneEven, baseboard, mapParams), baseboard, OshiUtil.getSystem().getBaseboard().getManufacturer() + " " + OshiUtil.getSystem().getBaseboard().getVersion())
.put(isNeedCollection(isNoneEven, ip, mapParams), ip, InetAddress.getLocalHost().getHostAddress())
.put(isNeedCollection(isNoneEven, cpuModel, mapParams), cpuModel, OshiUtil.getCpuInfo(0).getCpuModel())
.put(isNeedCollection(isNoneEven, cpuTemp, mapParams), cpuTemp, Double.parseDouble(new DecimalFormat("#.00").format(OshiUtil.getSensors().getCpuTemperature())))
.put(isNeedCollection(isNoneEven, cpuLoad, mapParams), cpuLoad, getCpuUsed())
.put(isNeedCollection(isNoneEven, memoryCap, mapParams), memoryCap, DataSizeUtil.format(OshiUtil.getMemory().getTotal()))
.put(isNeedCollection(isNoneEven, memoryAvailable, mapParams), memoryAvailable, DataSizeUtil.format(OshiUtil.getMemory().getAvailable()))
.put(isNeedCollection(isNoneEven, diskModel, mapParams), diskModel, collect1)
.put(isNeedCollection(isNoneEven, diskCap, mapParams), diskCap, collect)
.put(isNeedCollection(isNoneEven, diskFree, mapParams), diskFree, collect2)
.build();
log.info("采集数据,上报属性: mapData:{}", data);
Map mapR = restTemplate.postForObject("http://localhost:8765/uplink/oc-client", data, Map.class);
log.info("采集数据,上报属性: ret:{}", mapR);
} catch (Exception e) {
log.error("采集数据异常", e);
}
}
private boolean isNeedCollection(boolean isNoneEven, String key, Map<String, Integer> mapParams) {
if (null != mapParams && mapParams.containsKey(key)) {
return !isNoneEven || mapParams.get(key).equals(30);
}
return isNoneEven;
}
public static void main2(String[] args) throws InterruptedException {
/*String data = "[" +
"{\"code\":\"cpuLoad\",\"name\":\"CPU负载\",\"frequency\":30}," +
"{\"code\":\"cpuTemp\",\"name\":\"CPU温度\",\"frequency\":30}," +
"{\"code\":\"mac\",\"name\":\"MAC地址\",\"frequency\":30}," +
"{\"code\":\"memoryCap\",\"name\":\"内存容量\",\"frequency\":30}," +
"{\"code\":\"diskCap\",\"name\":\"硬盘容量\",\"frequency\":30}," +
"{\"code\":\"diskModel\",\"name\":\"硬盘型号\",\"frequency\":60}," +
"]";
List<ApqInfoDataVo> apqInfoDataVoss = new ArrayList<>();
ApqInfoDataVo apqInfoDataVo = new ApqInfoDataVo();
apqInfoDataVo.setCode("diskModel");
apqInfoDataVo.setName("硬盘型号");
apqInfoDataVo.setFrequency(60);
apqInfoDataVoss.add(apqInfoDataVo);
ApqInfoDataVo apqInfoDataVo2 = new ApqInfoDataVo();
apqInfoDataVo2.setCode("memoryCap");
apqInfoDataVo2.setName("内存容量");
apqInfoDataVo2.setFrequency(30);
apqInfoDataVoss.add(apqInfoDataVo2);
String s = JSONUtil.toJsonStr(apqInfoDataVoss);
System.out.println(s);
List<ApqInfoDataVo> apqInfoDataVos = JSONUtil.toList(data, ApqInfoDataVo.class);
List<Map> apqInfoDataVos2 = JSONUtil.toList(data, Map.class);*/
System.out.println(OshiUtil.getSensors().getCpuTemperature());
System.out.println(OshiUtil.getHardware().getDiskStores()[0].getModel());
System.out.println(DataSizeUtil.format(OshiUtil.getHardware().getDiskStores()[0].getReads()));
//System.out.println("CPU内存使用率:" + new DecimalFormat("#.##%").format((OshiUtil.getMemory().getAvailable() * 1.0 / OshiUtil.getMemory().getTotal())));
while (true) {
//System.out.println("CPU负载:" + new DecimalFormat("#.##%").format(OshiUtil.getCpuInfo().getUsed() / 100));
//System.out.println("硬盘剩余:" + OshiUtil.getHardware().getDiskStores()[0].getWriteBytes());
System.out.println(getCpuUsed());
Thread.sleep(3);
}
}
public static double getCpuUsed() {
/*SystemInfo systemInfo = new SystemInfo();
CentralProcessor processor = systemInfo.getHardware().getProcessor();
long[] prevTicks = processor.getSystemCpuLoadTicks();
long[] ticks = processor.getSystemCpuLoadTicks();
long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
//System.out.println("----------------cpu信息----------------");
//System.out.println("cpu核数:" + processor.getLogicalProcessorCount());
//System.out.println("cpu系统使用率:" + new DecimalFormat("#.##%").format(cSys * 1.0 / totalCpu));
//System.out.println("cpu用户使用率:" + new DecimalFormat("#.##%").format(user * 1.0 / totalCpu));
//System.out.println("cpu当前等待率:" + new DecimalFormat("#.##%").format(iowait * 1.0 / totalCpu));
//System.out.println("cpu当前使用率:" + new DecimalFormat("#.##%").format(1.0-(idle * 1.0 / totalCpu)));
return new BigDecimal((1.0 - (idle * 1.0 / totalCpu)) * 100).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();*/
CpuInfo cpuInfo = OshiUtil.getCpuInfo(100);
double used = Double.parseDouble(new DecimalFormat("#.00").format(100 - cpuInfo.getFree()));
return Math.min(Math.max(used, 0), 100);
}
private static void printDisks(List<HWDiskStore> list) {
System.out.println("Disks:");
for (HWDiskStore disk : list) {
boolean readwrite = disk.getReads() > 0 || disk.getWrites() > 0;
System.out.format(" %s: (model: %s - S/N: %s) size: %s, reads: %s (%s), writes: %s (%s), xfer: %s ms%n",
disk.getName(), disk.getModel(), disk.getSerial(),
disk.getSize() > 0 ? FormatUtil.formatBytesDecimal(disk.getSize()) : "?",
readwrite ? disk.getReads() : "?", readwrite ? FormatUtil.formatBytes(disk.getReadBytes()) : "?",
readwrite ? disk.getWrites() : "?", readwrite ? FormatUtil.formatBytes(disk.getWriteBytes()) : "?",
readwrite ? disk.getTransferTime() : "?");
List<HWPartition> partitions = Arrays.asList(disk.getPartitions());
if (partitions == null) {
// TODO Remove when all OS's implemented
continue;
}
for (HWPartition part : partitions) {
System.out.format(" |-- %s: %s (%s) Maj:Min=%d:%d, size: %s%s%n", part.getIdentification(),
part.getName(), part.getType(), part.getMajor(), part.getMinor(),
FormatUtil.formatBytesDecimal(part.getSize()),
part.getMountPoint().isEmpty() ? "" : " @ " + part.getMountPoint());
}
}
}
}
package com.priusis.job;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.priusis.dto.RegisterParamDto;
import com.priusis.utils.WinExecuteUtils;
import com.priusis.vo.MqttRpcDataMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Component
@ConditionalOnExpression("'${apq.job.type:null}'=='all' || '${apq.job.type:null}'=='register'")
public class ApqRegisterJob {
// "params":
// {
// "type":1
// "programs": [
// {
// "name":"qq"
// }
// ]
// }
@Autowired
private RestTemplate restTemplate;
@Scheduled(fixedDelay = 30000L)
protected void registerProgramTask() {
log.info("软件检测上报=================");
/* try {
WinExecuteUtils.killProc("TIM.exe");
} catch (IOException e) {
log.error("杀进程异常", e);
}*/
// 获取软件检测监控配置 params == data
ResponseEntity<MqttRpcDataMessage> forEntity = null;
try {
forEntity = restTemplate.getForEntity("http://localhost:8765/rpc_cmd/register", MqttRpcDataMessage.class);
} catch (RestClientException e) {
log.error("软件检测上报异常", e.getMessage());
}
if (null != forEntity) {
MqttRpcDataMessage body = forEntity.getBody();
String params = body.getParams();
if (StrUtil.isNotBlank(params)) {
Long sendTime = body.getSendTime();
//long current = System.currentTimeMillis();
RegisterParamDto registerParamDto = JSONUtil.toBean(params, RegisterParamDto.class);
// 收到软件检测下发请求
log.info("收到软件检测下发请求, sendTime:{}, params:{}", sendTime, params);
int type = registerParamDto.getType();
if (type == 1) {
List<RegisterParamDto.RegisterDetailParamDto> programs = registerParamDto.getPrograms();
// 上报软件检测监控数据
Map mapRequest = new HashMap();
for (RegisterParamDto.RegisterDetailParamDto program : programs) {
String name = program.getName().trim();
log.info("软件检测软件: {}", name);
boolean isE = WinExecuteUtils.findProcess(name);
if (isE) {
// 杀进程
log.info("存在黑名单软件, 进行进程查杀: {}", name);
try {
WinExecuteUtils.killProc(name);
} catch (Exception e) {
log.error("杀进程异常", e);
}
// 上报黑名单异常
mapRequest.put(name, "1");
}
}
// 上报黑名单异常
if (mapRequest.size() > 0) {
Map eventMapRequest = new HashMap();
eventMapRequest.put("requestId", 1);
eventMapRequest.put("methodName", "BlackList");
eventMapRequest.put("params", mapRequest);
Map map = restTemplate.postForObject("http://localhost:8765/uplink_event/oc-client", eventMapRequest, Map.class);
log.info("存在软件检测接口扫码告警,上报告警事件: mapData:{}, ret:{}", mapRequest, map);
}
// 上报黑名单属性 todo
}
} else {
log.info("未获取到获取软件检测监控配置");
}
} else {
log.info("未获取到获取软件检测监控配置");
}
}
}
......@@ -2,13 +2,7 @@ package com.priusis.utils;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.system.ApplicationHome;
import java.io.File;
import java.io.UnsupportedEncodingException;
/******************************************************************************************************************************
......
package com.priusis.util;
package com.priusis.utils;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
......
package com.priusis.util;
package com.priusis.utils;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
......
package com.priusis;
import com.priusis.vo.MqttRpcDataMessage;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.Map;
@RunWith(SpringRunner.class)
@SpringBootTest
public class RestTest {
@Autowired
private RestTemplate restTemplate;
@Test
public void test1() throws Exception {
// 获取硬件监控配置 params == data
ResponseEntity<MqttRpcDataMessage> forEntity = restTemplate.getForEntity("http://localhost:8765/rpc_cmd/controll", MqttRpcDataMessage.class);
System.out.println(forEntity.getBody().getMethod());
System.out.println(forEntity.getBody().getParams());
// 上报硬件监控数据
Map mapRequest = new HashMap();
Map map = restTemplate.postForObject("http://localhost:8765/uplink/oc-client", mapRequest, Map.class);
System.out.println(map);
}
}
......@@ -57,25 +57,10 @@
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.11</version>
</dependency>
<dependency>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
<version>${jna.version}</version>
</dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
<groupId>com.priusis</groupId>
<artifactId>apq-pc-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
......
package com.priusis;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.priusis.dto.HwPortControllerDto;
import com.priusis.utils.IHwPortController;
import com.priusis.vo.MqttRpcDataMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@Slf4j
@EnableScheduling
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, SecurityAutoConfiguration.class})
public class ApqControlApplication {
// 一分钟一次上报
private final Long FIXED_DELAY = 60000L;
@Autowired
private RestTemplate restTemplate;
public static void main(String[] args) {
SpringApplication.run(ApqControlApplication.class, args);
}
@Scheduled(fixedDelay = 60000L)
protected void controlProgramTask() {
log.info("硬件监控上报=================");
// todo
//testUsb();
// 获取硬件监控配置 params == data
ResponseEntity<MqttRpcDataMessage> forEntity = null;
try {
forEntity = restTemplate.getForEntity("http://localhost:8765/rpc_cmd/controll", MqttRpcDataMessage.class);
} catch (Exception e) {
log.error("硬件监控上报异常", e.getMessage());
}
if (null != forEntity) {
MqttRpcDataMessage body = forEntity.getBody();
String params = body.getParams();
if (StrUtil.isNotBlank(params)) {
Long sendTime = body.getSendTime();
long current = System.currentTimeMillis();
List<HwPortControllerDto> hwPortControllerDtos = JSONUtil.toList(params, HwPortControllerDto.class);
// 初始化硬件接口管理模块
int result = IHwPortController.instanceDll.APQ_HWPORT_Initialize();
log.info("APQ_HWPORT_Initialize ret:{}", result);
if (current - sendTime <= FIXED_DELAY && CollUtil.isNotEmpty(hwPortControllerDtos)) {
// 收到硬件策略下发请求
log.info("收到硬件策略下发请求, sendTime:{}, params:{}", sendTime, params);
for (HwPortControllerDto hwPortControllerDto : hwPortControllerDtos) {
HwPortControllerDto.DeviceHardwareEnum deviceHardwareEnum = hwPortControllerDto.getKey();
int doType = hwPortControllerDto.getDoType();
int limitType = hwPortControllerDto.getLimitType();
int value = hwPortControllerDto.getValue();
List<Integer> hwDeviceIds = deviceHardwareEnum.getHwDeviceIds();
String hwDeviceName = deviceHardwareEnum.getName();
// 设置普通设备权限
if (Objects.equals(deviceHardwareEnum.getHwGroup(), "Normal")) {
// 1F/2T
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
int result32 = IHwPortController.instanceDll.APQ_HWPORT_set_normal_device_permit(hwDeviceId, perm, null);
log.info("APQ_HWPORT_set_normal_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result32);
}
} else if (Objects.equals(deviceHardwareEnum.getHwGroup(), "Storage")) { // 设置存储设备权限
// 1F/2T/3T-ALL/4T-R/5T-CI/6T-CO 拷出目前无用!! Storage移动硬盘,TYPEC 无效 !!
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
if (perm == 2) {
// limitType 1读写 2只读 3拷入 4拷出 5不限速 6限速
perm = (limitType == 1 ? 3 : limitType == 2 ? 4 : limitType == 3 ? 5 : limitType == 4 ? 6 : 3);
}
int result32 = IHwPortController.instanceDll.APQ_HWPORT_set_storage_device_permit(hwDeviceId, perm, null);
log.info("APQ_HWPORT_set_storage_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result32);
}
} else if (Objects.equals(deviceHardwareEnum.getHwGroup(), "NET")) { // 设置网络设备权限
// 1F/2T/3T-NS/4T-S-200 网口,4G/5G模块,无线WIFI区分不了 !!
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
if (perm == 2) {
// limitType 1读写 2只读 3拷入 4拷出 5不限速 6限速
perm = (limitType == 5 ? 3 : limitType == 6 ? 4 : 2);
}
int result32 = IHwPortController.instanceDll.APQ_HWPORT_set_net_device_permit(hwDeviceId, perm, value, null);
log.info("APQ_HWPORT_set_net_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result32);
}
}
// 应用硬件接口管理模块的配置内容
int result5 = IHwPortController.instanceDll.APQ_HWPORT_Apply();
log.info("APQ_HWPORT_Apply ret:{}", result5);
}
} else {
log.info("执行硬件监控, sendTime:{}, params:{}", sendTime, params);
// 上报硬件监控数据
Map mapRequest = new HashMap();
for (HwPortControllerDto hwPortControllerDto : hwPortControllerDtos) {
HwPortControllerDto.DeviceHardwareEnum deviceHardwareEnum = hwPortControllerDto.getKey();
int doType = hwPortControllerDto.getDoType();
int limitType = hwPortControllerDto.getLimitType();
int value = hwPortControllerDto.getValue();
List<Integer> hwDeviceIds = deviceHardwareEnum.getHwDeviceIds();
String hwDeviceName = deviceHardwareEnum.getName();
// 设置普通设备权限
if (Objects.equals(deviceHardwareEnum.getHwGroup(), "Normal")) {
// 1F/2T
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
if (perm == 1) {
// 获取普通设备权限
int result31 = IHwPortController.instanceDll.APQ_HWPORT_get_normal_device_permit(hwDeviceId);
log.debug("APQ_HWPORT_get_normal_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result31);
if (result31 == 2) {
mapRequest.put(deviceHardwareEnum.name(), perm);
}
}
}
} else if (Objects.equals(deviceHardwareEnum.getHwGroup(), "Storage")) { // 设置存储设备权限
// 1F/2T/3T-ALL/4T-R/5T-CI/6T-CO 拷出目前无用!! Storage移动硬盘,TYPEC 无效 !!
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
if (perm == 2) {
// limitType 1读写 2只读 3拷入 4拷出 5不限速 6限速
perm = (limitType == 1 ? 3 : limitType == 2 ? 4 : limitType == 3 ? 5 : limitType == 4 ? 6 : 3);
}
int result32 = IHwPortController.instanceDll.APQ_HWPORT_get_storage_device_permit(hwDeviceId);
log.info("APQ_HWPORT_get_storage_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result32);
if (perm != result32) {
mapRequest.put(deviceHardwareEnum.name(), perm);
}
}
} else if (Objects.equals(deviceHardwareEnum.getHwGroup(), "NET")) { // 设置网络设备权限
// 1F/2T/3T-NS/4T-S-200 网口,4G/5G模块,无线WIFI区分不了 !!
for (Integer hwDeviceId : hwDeviceIds) {
int perm = (doType == 1 ? 2 : 1);
if (perm == 2) {
// limitType 1读写 2只读 3拷入 4拷出 5不限速 6限速
perm = (limitType == 5 ? 3 : limitType == 6 ? 4 : 2);
}
int result32 = IHwPortController.instanceDll.APQ_HWPORT_get_net_device_permit(hwDeviceId, 0);
log.info("APQ_HWPORT_get_net_device_permit doType:{}, limitType;{},value:{}, hwDeviceId:{}, name;{}, perm:{}, ret:{}",
doType, limitType, value, hwDeviceId, hwDeviceName, perm, result32);
if (perm != result32) {
mapRequest.put(deviceHardwareEnum.name(), perm);
}
}
}
}
if (mapRequest.size() > 0) {
Map eventMapRequest = new HashMap();
eventMapRequest.put("methodName", "control_warning");
eventMapRequest.put("params", mapRequest);
Map map = restTemplate.postForObject("http://localhost:8765/uplink_event/oc-client", eventMapRequest, Map.class);
log.info("存在硬件接口扫码告警,上报告警事件: mapData:{}, ret:{}", mapRequest, map);
}
}
// 清理硬件接口管理模块
int result2 = IHwPortController.instanceDll.APQ_HWPORT_Uninitialize();
log.info("APQ_HWPORT_Uninitialize ret:{}", result2);
} else {
log.info("未获取到获取硬件监控配置");
}
} else {
log.info("未获取到获取硬件监控配置");
//int result = IHwPortController.instanceDll.APQ_HWPORT_Initialize();
//log.info("APQ_HWPORT_Initialize ret:{}", result);
//int result2 = IHwPortController.instanceDll.APQ_HWPORT_Uninitialize();
//log.info("APQ_HWPORT_Uninitialize ret:{}", result2);
}
}
public void testUsb() {
// 初始化硬件接口管理模块
int result = IHwPortController.instanceDll.APQ_HWPORT_Initialize();
log.info("APQ_HWPORT_Initialize ret:{}", result);
// APQ_HWPORT_STORAGE_PERM_ALLOW APQ_HWPORT_STORAGE_PERM_DENY
int result32 = IHwPortController.instanceDll.APQ_HWPORT_set_storage_device_permit(IHwPortController.HwportStorageDevidEnum.APQ_HWPORT_STORAGE_DEVID_UDISK.getCode(), IHwPortController.HwportStoragePermEnum.APQ_HWPORT_STORAGE_PERM_ALLOW.getCode(), null);
log.info("APQ_HWPORT_set_storage_device_permit ret:{}", result32);
//应用硬件接口管理模块的配置内容
int result5 = IHwPortController.instanceDll.APQ_HWPORT_Apply();
log.info("APQ_HWPORT_Apply ret:{}", result5);
int result2 = IHwPortController.instanceDll.APQ_HWPORT_Uninitialize();
log.info("APQ_HWPORT_Uninitialize ret:{}", result2);
}
}
......@@ -6,4 +6,8 @@ server:
# Server bind address
address: "0.0.0.0"
# port: ${random.int[10000,19999]}
port: 8762
\ No newline at end of file
port: 8762
apq:
job:
type: control
\ No newline at end of file
......@@ -16,9 +16,9 @@
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${pkg.logFolder}/${pkg.name}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<maxFileSize>10MB</maxFileSize>
<maxHistory>3</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
......
......@@ -44,6 +44,13 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.priusis</groupId>
<artifactId>apq-pc-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
......@@ -55,17 +62,6 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.11</version>
</dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
......
package com.priusis;
import cn.hutool.core.io.unit.DataSizeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.system.oshi.CpuInfo;
import cn.hutool.system.oshi.OshiUtil;
import com.priusis.util.MacAddrUtil;
import com.priusis.vo.ApqInfoDataVo;
import com.priusis.vo.MqttRpcDataMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.client.RestTemplate;
import oshi.hardware.HWDiskStore;
import oshi.hardware.HWPartition;
import oshi.util.FormatUtil;
import java.io.File;
import java.net.InetAddress;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Slf4j
@EnableScheduling
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, SecurityAutoConfiguration.class})
public class ApqInfoApplication {
@Autowired
private RestTemplate restTemplate;
private int runningIndex = 0;
public static void main(String[] args) {
SpringApplication.run(ApqInfoApplication.class, args);
}
// 30秒一次上报
@Scheduled(fixedDelay = 30000L)
protected void controlProgramTask() {
log.info("设备实时数据采集上报=================");
runningIndex++;
boolean isNoneEven = runningIndex % 2 == 0;
// 获取采集配置,数据上报频率 params == data
ResponseEntity<MqttRpcDataMessage> forEntity = null;
Map<String, Integer> mapParams = null;
try {
forEntity = restTemplate.getForEntity("http://localhost:8765/rpc_cmd/info", MqttRpcDataMessage.class);
if (null != forEntity) {
MqttRpcDataMessage body = forEntity.getBody();
String params = body.getParams();
if (StrUtil.isNotBlank(params)) {
List<ApqInfoDataVo> apqInfoDataVos = JSONUtil.toList(params, ApqInfoDataVo.class);
mapParams = new HashMap<>();
for (ApqInfoDataVo apqInfoDataVo : apqInfoDataVos) {
mapParams.put(apqInfoDataVo.getCode(), apqInfoDataVo.getFrequency());
}
}
}
} catch (Exception e) {
log.error("采集数据异常", e);
}
String operatingSystem = "operatingSystem";
String mac = "mac";
String baseboard = "baseboard";
String ip = "ip";
String cpuModel = "cpuModel";
String cpuLoad = "cpuLoad";
String cpuTemp = "cpuTemp";
String memoryCap = "memoryCap";
String memoryAvailable = "memoryAvailable";
String diskModel = "diskModel";
String diskCap = "diskCap";
String diskFree = "diskFree";
try {
// 上报PC实时信息
String collect = null;
String collect1 = null;
String collect2 = null;
try {
collect = Arrays.stream(OshiUtil.getHardware().getDiskStores())
.map(HWDiskStore::getPartitions)
.flatMap(Arrays::stream)
.filter(partition -> StrUtil.isNotBlank(partition.getMountPoint()))
.map(partition -> "\"" + StrUtil.removeSuffix(partition.getMountPoint(), ":\\") + "盘\":\"" +
DataSizeUtil.format(partition.getSize()) + "\"")
.collect(Collectors.joining(",", "{", "}"));
collect1 = Arrays.stream(OshiUtil.getHardware().getDiskStores())
.map(store -> Arrays.stream(store.getPartitions())
.map(HWPartition::getMountPoint)
.filter(StrUtil::isNotBlank)
.map(s -> "\"" + StrUtil.removeSuffix(s, ":\\") + "盘\":\"" +
StrUtil.removeSuffix(store.getModel(), " (标准磁盘驱动器)") + "\"")
.collect(Collectors.joining(",")))
.filter(StrUtil::isNotBlank)
.collect(Collectors.joining(",", "{", "}"));
collect2 = Arrays.stream(OshiUtil.getHardware().getDiskStores())
.map(HWDiskStore::getPartitions)
.flatMap(Arrays::stream)
.filter(partition -> StrUtil.isNotBlank(partition.getMountPoint()))
.map(partition -> "\"" + StrUtil.removeSuffix(partition.getMountPoint(), ":\\") + "盘\":\"" +
new DecimalFormat("#.00").format(100d * new File(partition.getMountPoint()).getFreeSpace() / partition.getSize()) + "%\"")
.collect(Collectors.joining(",", "{", "}"));
} catch (Exception e) {
log.error("硬盘数据获取失败", e);
}
Map<String, Object> data = MapUtil.<String, Object>builder()
.put(isNeedCollection(isNoneEven, operatingSystem, mapParams), operatingSystem, OshiUtil.getOs().toString())
.put(isNeedCollection(isNoneEven, mac, mapParams), mac, MacAddrUtil.get())
.put(isNeedCollection(isNoneEven, baseboard, mapParams), baseboard, OshiUtil.getSystem().getBaseboard().getManufacturer() + " " + OshiUtil.getSystem().getBaseboard().getVersion())
.put(isNeedCollection(isNoneEven, ip, mapParams), ip, InetAddress.getLocalHost().getHostAddress())
.put(isNeedCollection(isNoneEven, cpuModel, mapParams), cpuModel, OshiUtil.getCpuInfo(0).getCpuModel())
.put(isNeedCollection(isNoneEven, cpuTemp, mapParams), cpuTemp, Double.parseDouble(new DecimalFormat("#.00").format(OshiUtil.getSensors().getCpuTemperature())))
.put(isNeedCollection(isNoneEven, cpuLoad, mapParams), cpuLoad, getCpuUsed())
.put(isNeedCollection(isNoneEven, memoryCap, mapParams), memoryCap, DataSizeUtil.format(OshiUtil.getMemory().getTotal()))
.put(isNeedCollection(isNoneEven, memoryAvailable, mapParams), memoryAvailable, DataSizeUtil.format(OshiUtil.getMemory().getAvailable()))
.put(isNeedCollection(isNoneEven, diskModel, mapParams), diskModel, collect1)
.put(isNeedCollection(isNoneEven, diskCap, mapParams), diskCap, collect)
.put(isNeedCollection(isNoneEven, diskFree, mapParams), diskFree, collect2)
.build();
log.info("采集数据,上报属性: mapData:{}", data);
Map mapR = restTemplate.postForObject("http://localhost:8765/uplink/oc-client", data, Map.class);
log.info("采集数据,上报属性: ret:{}", mapR);
} catch (Exception e) {
log.error("采集数据异常", e);
}
}
private boolean isNeedCollection(boolean isNoneEven, String key, Map<String, Integer> mapParams) {
if (null != mapParams && mapParams.containsKey(key)) {
return !isNoneEven || mapParams.get(key).equals(30);
}
return isNoneEven;
}
public static void main2(String[] args) throws InterruptedException {
/*String data = "[" +
"{\"code\":\"cpuLoad\",\"name\":\"CPU负载\",\"frequency\":30}," +
"{\"code\":\"cpuTemp\",\"name\":\"CPU温度\",\"frequency\":30}," +
"{\"code\":\"mac\",\"name\":\"MAC地址\",\"frequency\":30}," +
"{\"code\":\"memoryCap\",\"name\":\"内存容量\",\"frequency\":30}," +
"{\"code\":\"diskCap\",\"name\":\"硬盘容量\",\"frequency\":30}," +
"{\"code\":\"diskModel\",\"name\":\"硬盘型号\",\"frequency\":60}," +
"]";
List<ApqInfoDataVo> apqInfoDataVoss = new ArrayList<>();
ApqInfoDataVo apqInfoDataVo = new ApqInfoDataVo();
apqInfoDataVo.setCode("diskModel");
apqInfoDataVo.setName("硬盘型号");
apqInfoDataVo.setFrequency(60);
apqInfoDataVoss.add(apqInfoDataVo);
ApqInfoDataVo apqInfoDataVo2 = new ApqInfoDataVo();
apqInfoDataVo2.setCode("memoryCap");
apqInfoDataVo2.setName("内存容量");
apqInfoDataVo2.setFrequency(30);
apqInfoDataVoss.add(apqInfoDataVo2);
String s = JSONUtil.toJsonStr(apqInfoDataVoss);
System.out.println(s);
List<ApqInfoDataVo> apqInfoDataVos = JSONUtil.toList(data, ApqInfoDataVo.class);
List<Map> apqInfoDataVos2 = JSONUtil.toList(data, Map.class);*/
System.out.println(OshiUtil.getSensors().getCpuTemperature());
System.out.println(OshiUtil.getHardware().getDiskStores()[0].getModel());
System.out.println(DataSizeUtil.format(OshiUtil.getHardware().getDiskStores()[0].getReads()));
//System.out.println("CPU内存使用率:" + new DecimalFormat("#.##%").format((OshiUtil.getMemory().getAvailable() * 1.0 / OshiUtil.getMemory().getTotal())));
while (true) {
//System.out.println("CPU负载:" + new DecimalFormat("#.##%").format(OshiUtil.getCpuInfo().getUsed() / 100));
//System.out.println("硬盘剩余:" + OshiUtil.getHardware().getDiskStores()[0].getWriteBytes());
System.out.println(getCpuUsed());
Thread.sleep(3);
}
}
public static double getCpuUsed() {
/*SystemInfo systemInfo = new SystemInfo();
CentralProcessor processor = systemInfo.getHardware().getProcessor();
long[] prevTicks = processor.getSystemCpuLoadTicks();
long[] ticks = processor.getSystemCpuLoadTicks();
long nice = ticks[CentralProcessor.TickType.NICE.getIndex()] - prevTicks[CentralProcessor.TickType.NICE.getIndex()];
long irq = ticks[CentralProcessor.TickType.IRQ.getIndex()] - prevTicks[CentralProcessor.TickType.IRQ.getIndex()];
long softirq = ticks[CentralProcessor.TickType.SOFTIRQ.getIndex()] - prevTicks[CentralProcessor.TickType.SOFTIRQ.getIndex()];
long steal = ticks[CentralProcessor.TickType.STEAL.getIndex()] - prevTicks[CentralProcessor.TickType.STEAL.getIndex()];
long cSys = ticks[CentralProcessor.TickType.SYSTEM.getIndex()] - prevTicks[CentralProcessor.TickType.SYSTEM.getIndex()];
long user = ticks[CentralProcessor.TickType.USER.getIndex()] - prevTicks[CentralProcessor.TickType.USER.getIndex()];
long iowait = ticks[CentralProcessor.TickType.IOWAIT.getIndex()] - prevTicks[CentralProcessor.TickType.IOWAIT.getIndex()];
long idle = ticks[CentralProcessor.TickType.IDLE.getIndex()] - prevTicks[CentralProcessor.TickType.IDLE.getIndex()];
long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
//System.out.println("----------------cpu信息----------------");
//System.out.println("cpu核数:" + processor.getLogicalProcessorCount());
//System.out.println("cpu系统使用率:" + new DecimalFormat("#.##%").format(cSys * 1.0 / totalCpu));
//System.out.println("cpu用户使用率:" + new DecimalFormat("#.##%").format(user * 1.0 / totalCpu));
//System.out.println("cpu当前等待率:" + new DecimalFormat("#.##%").format(iowait * 1.0 / totalCpu));
//System.out.println("cpu当前使用率:" + new DecimalFormat("#.##%").format(1.0-(idle * 1.0 / totalCpu)));
return new BigDecimal((1.0 - (idle * 1.0 / totalCpu)) * 100).setScale(2, BigDecimal.ROUND_DOWN).doubleValue();*/
CpuInfo cpuInfo = OshiUtil.getCpuInfo(100);
double used = Double.parseDouble(new DecimalFormat("#.00").format(100 - cpuInfo.getFree()));
return Math.min(Math.max(used, 0), 100);
}
private static void printDisks(List<HWDiskStore> list) {
System.out.println("Disks:");
for (HWDiskStore disk : list) {
boolean readwrite = disk.getReads() > 0 || disk.getWrites() > 0;
System.out.format(" %s: (model: %s - S/N: %s) size: %s, reads: %s (%s), writes: %s (%s), xfer: %s ms%n",
disk.getName(), disk.getModel(), disk.getSerial(),
disk.getSize() > 0 ? FormatUtil.formatBytesDecimal(disk.getSize()) : "?",
readwrite ? disk.getReads() : "?", readwrite ? FormatUtil.formatBytes(disk.getReadBytes()) : "?",
readwrite ? disk.getWrites() : "?", readwrite ? FormatUtil.formatBytes(disk.getWriteBytes()) : "?",
readwrite ? disk.getTransferTime() : "?");
List<HWPartition> partitions = Arrays.asList(disk.getPartitions());
if (partitions == null) {
// TODO Remove when all OS's implemented
continue;
}
for (HWPartition part : partitions) {
System.out.format(" |-- %s: %s (%s) Maj:Min=%d:%d, size: %s%s%n", part.getIdentification(),
part.getName(), part.getType(), part.getMajor(), part.getMinor(),
FormatUtil.formatBytesDecimal(part.getSize()),
part.getMountPoint().isEmpty() ? "" : " @ " + part.getMountPoint());
}
}
}
}
......@@ -7,7 +7,7 @@ import cn.hutool.json.JSONUtil;
import cn.hutool.system.oshi.CpuInfo;
import cn.hutool.system.oshi.OshiUtil;
import com.priusis.lib.R;
import com.priusis.util.MacAddrUtil;
import com.priusis.utils.MacAddrUtil;
import com.priusis.vo.ApqInfoDataVo;
import com.priusis.vo.MqttRpcDataMessage;
import lombok.extern.slf4j.Slf4j;
......
package com.priusis.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class MqttRpcDataMessage implements Serializable {
private static final long serialVersionUID = -3133461476074777891L;
private int requestId;
private String method;
private String params;
@Override
public String toString() {
return "{requestId=" + requestId +
", method=" + method +
", params=" + params +
'}';
}
}
......@@ -7,3 +7,7 @@ server:
address: "0.0.0.0"
# port: ${random.int[10000,19999]}
port: 8764
apq:
job:
type: info
\ No newline at end of file
......@@ -16,9 +16,9 @@
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${pkg.logFolder}/${pkg.name}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<maxFileSize>10MB</maxFileSize>
<maxHistory>3</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
......
......@@ -3,7 +3,7 @@ package com.priusis;
import cn.hutool.core.io.unit.DataSizeUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.system.oshi.OshiUtil;
import com.priusis.util.MacAddrUtil;
import com.priusis.utils.MacAddrUtil;
import com.priusis.vo.MqttRpcDataMessage;
import org.junit.Test;
import org.junit.runner.RunWith;
......
......@@ -56,16 +56,10 @@
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.11</version>
<groupId>com.priusis</groupId>
<artifactId>apq-pc-common</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
......
package com.priusis;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.priusis.dto.RegisterParamDto;
import com.priusis.util.WinExecuteUtils;
import com.priusis.vo.MqttRpcDataMessage;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@EnableScheduling
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, SecurityAutoConfiguration.class})
public class ApqRegisterApplication {
......@@ -30,92 +14,5 @@ public class ApqRegisterApplication {
SpringApplication.run(ApqRegisterApplication.class, args);
}
// "params":
// {
// "type":1
// "programs": [
// {
// "name":"qq"
// }
// ]
// }
@Autowired
private RestTemplate restTemplate;
@Scheduled(fixedDelay = 30000L)
protected void registerProgramTask() {
log.info("软件检测上报=================");
/* try {
WinExecuteUtils.killProc("TIM.exe");
} catch (IOException e) {
log.error("杀进程异常", e);
}*/
// 获取软件检测监控配置 params == data
ResponseEntity<MqttRpcDataMessage> forEntity = null;
try {
forEntity = restTemplate.getForEntity("http://localhost:8765/rpc_cmd/register", MqttRpcDataMessage.class);
} catch (RestClientException e) {
log.error("软件检测上报异常", e.getMessage());
}
if (null != forEntity) {
MqttRpcDataMessage body = forEntity.getBody();
String params = body.getParams();
if (StrUtil.isNotBlank(params)) {
Long sendTime = body.getSendTime();
//long current = System.currentTimeMillis();
RegisterParamDto registerParamDto = JSONUtil.toBean(params, RegisterParamDto.class);
// 收到软件检测下发请求
log.info("收到软件检测下发请求, sendTime:{}, params:{}", sendTime, params);
int type = registerParamDto.getType();
if (type == 1) {
List<RegisterParamDto.RegisterDetailParamDto> programs = registerParamDto.getPrograms();
// 上报软件检测监控数据
Map mapRequest = new HashMap();
for (RegisterParamDto.RegisterDetailParamDto program : programs) {
String name = program.getName().trim();
log.info("软件检测软件: {}", name);
boolean isE = WinExecuteUtils.findProcess(name);
if (isE) {
// 杀进程
log.info("存在黑名单软件, 进行进程查杀: {}", name);
try {
WinExecuteUtils.killProc(name);
} catch (Exception e) {
log.error("杀进程异常", e);
}
// 上报黑名单异常
mapRequest.put(name, "1");
}
}
// 上报黑名单异常
if (mapRequest.size() > 0) {
Map eventMapRequest = new HashMap();
eventMapRequest.put("requestId", 1);
eventMapRequest.put("methodName", "BlackList");
eventMapRequest.put("params", mapRequest);
Map map = restTemplate.postForObject("http://localhost:8765/uplink_event/oc-client", eventMapRequest, Map.class);
log.info("存在软件检测接口扫码告警,上报告警事件: mapData:{}, ret:{}", mapRequest, map);
}
// 上报黑名单属性 todo
}
} else {
log.info("未获取到获取软件检测监控配置");
}
} else {
log.info("未获取到获取软件检测监控配置");
}
}
}
package com.priusis.vo;
import lombok.Data;
import java.io.Serializable;
@Data
public class MqttRpcDataMessage implements Serializable {
private static final long serialVersionUID = -3133461476074777891L;
private int requestId;
private String method;
private Long sendTime;
private String params;
@Override
public String toString() {
return "{requestId=" + requestId +
", sendTime=" + sendTime +
", method=" + method +
", params=" + params +
'}';
}
}
......@@ -6,4 +6,8 @@ server:
# Server bind address
address: "0.0.0.0"
# port: ${random.int[30000,39999]}
port: 8763
\ No newline at end of file
port: 8763
apq:
job:
type: register
\ No newline at end of file
......@@ -16,9 +16,9 @@
<rollingPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${pkg.logFolder}/${pkg.name}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>100MB</maxFileSize>
<maxHistory>30</maxHistory>
<totalSizeCap>3GB</totalSizeCap>
<maxFileSize>10MB</maxFileSize>
<maxHistory>3</maxHistory>
<totalSizeCap>100MB</totalSizeCap>
</rollingPolicy>
<encoder>
<pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
......
......@@ -11,6 +11,7 @@
<name>apq-client</name>
<modules>
<module>apq-pc-common</module>
<module>apq-pc-client</module>
<module>apq-pc-control</module>
<module>apq-pc-info</module>
......
......@@ -17,8 +17,8 @@
-->
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Apache_Logo_Horizontal" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
x="0px" y="0px" viewBox="0 0 9835 1713.9" enable-background="new 0 0 9835 1713.9" xml:space="preserve">
<svg version="1.1" id="Apache_Logo_Horizontal" xmlns="http://www.w3.org/2000/svg"
x="0px" y="0px" viewBox="0 0 9835 1713.9" enable-background="new 0 0 9835 1713.9" xml:space="preserve">
<path fill="#6D6E71" d="M1069.6,296.4v92.2h-11.8v-92.2h-33.7V285h79.4v11.4H1069.6z"/>
<path fill="#6D6E71" d="M1234.8,388.5V343h-62.4v45.6h-11.8V285h11.8v46.8h62.4V285h11.8v103.6H1234.8z"/>
<path fill="#6D6E71" d="M1329.2,296.4v34h52.2v11.4h-52.2v35.5h60.4v11.3h-72.2V285h70.3v11.4H1329.2z"/>
......
......@@ -29,11 +29,11 @@
<!ENTITY ns_svg "http://www.w3.org/2000/svg">
<!ENTITY ns_xlink "http://www.w3.org/1999/xlink">
]>
<svg
xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" xmlns:graph="&ns_graphs;" i:viewOrigin="176.7139 486.707" i:rulerOrigin="-156 -296" i:pageBounds="156 496 456 296"
xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
width="260.162" height="184.413" viewBox="0 0 260.162 184.413" overflow="visible" enable-background="new 0 0 260.162 184.413"
xml:space="preserve">
<svg
xmlns:x="&ns_extend;" xmlns:i="&ns_ai;" i:viewOrigin="176.7139 486.707" i:rulerOrigin="-156 -296" i:pageBounds="156 496 456 296"
xmlns="&ns_svg;" xmlns:xlink="&ns_xlink;"
width="260.162" height="184.413" viewBox="0 0 260.162 184.413" overflow="visible" enable-background="new 0 0 260.162 184.413"
xml:space="preserve">
<metadata>
<variableSets xmlns="&ns_vars;">
<variableSet varSetName="binding1" locked="none">
......@@ -46,14 +46,14 @@
<sliceSourceBounds y="302.294" x="176.714" width="260.162" height="184.413" bottomLeftOrigin="true"></sliceSourceBounds>
</sfw>
<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?><x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='XMP toolkit 3.0-29, framework 1.6'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:iX='http://ns.adobe.com/iX/1.0/'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
<rdf:Description rdf:about=''
xmlns:pdf='http://ns.adobe.com/pdf/1.3/'>
>
</rdf:Description>
<rdf:Description rdf:about=''
xmlns:tiff='http://ns.adobe.com/tiff/1.0/'>
<rdf:Description rdf:about=''
>
</rdf:Description>
<rdf:Description rdf:about=''
......
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class index_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论