agent定时更新优化、脚本策略定时执行优化
优化ipv4、ipv6采集
This commit is contained in:
@@ -225,9 +225,9 @@ public class AgentEndpoint {
|
|||||||
if(StringUtils.isNotBlank(md5) && StringUtils.isNotBlank(versionUpdateEO.getFileMd5())
|
if(StringUtils.isNotBlank(md5) && StringUtils.isNotBlank(versionUpdateEO.getFileMd5())
|
||||||
&& StringUtils.equals(md5,versionUpdateEO.getFileMd5())){
|
&& StringUtils.equals(md5,versionUpdateEO.getFileMd5())){
|
||||||
//更改全局变量
|
//更改全局变量
|
||||||
GlobalConfig.isCollect = false;
|
// GlobalConfig.isCollect = false;
|
||||||
//调用采集任务
|
//调用采集任务
|
||||||
agentService.cancelCollect();
|
// agentService.cancelCollect();
|
||||||
//所有文件下载完成,执行脚本命令
|
//所有文件下载完成,执行脚本命令
|
||||||
agentService.command(policy, clientId,MsgEnum.Agent版本更新应答.getValue());
|
agentService.command(policy, clientId,MsgEnum.Agent版本更新应答.getValue());
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -97,6 +97,8 @@ public class AppInitializer implements CommandLineRunner {
|
|||||||
agentService.checkFirewall();
|
agentService.checkFirewall();
|
||||||
AssertLog.info("启动检查防火墙策略定时任务 - 延迟: {}ms, 间隔: {}ms", milli, 600000);
|
AssertLog.info("启动检查防火墙策略定时任务 - 延迟: {}ms, 间隔: {}ms", milli, 600000);
|
||||||
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
||||||
|
AssertLog.info("检测agent更新配置");
|
||||||
|
agentService.checkAgentUpdate();
|
||||||
|
|
||||||
}else{
|
}else{
|
||||||
//未注册,发送注册
|
//未注册,发送注册
|
||||||
|
|||||||
@@ -852,6 +852,8 @@ public class BusinessTasks {
|
|||||||
agentService.checkFirewall();
|
agentService.checkFirewall();
|
||||||
AssertLog.info("启动检查防火墙策略定时任务 - 延迟: {}ms, 间隔: {}ms", milli, 600000);
|
AssertLog.info("启动检查防火墙策略定时任务 - 延迟: {}ms, 间隔: {}ms", milli, 600000);
|
||||||
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
||||||
|
AssertLog.info("检测agent更新配置");
|
||||||
|
agentService.checkAgentUpdate();
|
||||||
}else{
|
}else{
|
||||||
//未注册,发送注册
|
//未注册,发送注册
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -2,12 +2,15 @@ package com.tongran.agent.client.scheduler.task;
|
|||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.tongran.agent.client.core.config.ApplicationProperties;
|
import com.tongran.agent.client.core.config.ApplicationProperties;
|
||||||
|
import com.tongran.agent.client.core.config.GlobalConfig;
|
||||||
import com.tongran.agent.client.core.enums.MsgEnum;
|
import com.tongran.agent.client.core.enums.MsgEnum;
|
||||||
import com.tongran.agent.client.core.session.SessionManager;
|
import com.tongran.agent.client.core.session.SessionManager;
|
||||||
import com.tongran.agent.client.netty.model.Message;
|
import com.tongran.agent.client.netty.model.Message;
|
||||||
import com.tongran.agent.client.scheduler.service.AsyncCommandExecutor;
|
import com.tongran.agent.client.scheduler.service.AsyncCommandExecutor;
|
||||||
|
import com.tongran.agent.client.service.AgentService;
|
||||||
import com.tongran.agent.client.utils.AgentDataUtil;
|
import com.tongran.agent.client.utils.AgentDataUtil;
|
||||||
import com.tongran.agent.client.utils.AgentUtil;
|
import com.tongran.agent.client.utils.AgentUtil;
|
||||||
|
import com.tongran.agent.client.utils.AssertLog;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
@@ -27,6 +30,8 @@ public class SpecificTimeTaskService {
|
|||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private ApplicationProperties properties;
|
private ApplicationProperties properties;
|
||||||
|
@Resource
|
||||||
|
private AgentService agentService;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private SpecificTimeTaskConfig taskConfig;
|
private SpecificTimeTaskConfig taskConfig;
|
||||||
@@ -81,6 +86,11 @@ public class SpecificTimeTaskService {
|
|||||||
String key = request.getTaskName()+"-"+System.currentTimeMillis();
|
String key = request.getTaskName()+"-"+System.currentTimeMillis();
|
||||||
if(StringUtils.equals(request.getDataType(), MsgEnum.Agent版本更新应答.getValue())){
|
if(StringUtils.equals(request.getDataType(), MsgEnum.Agent版本更新应答.getValue())){
|
||||||
try {
|
try {
|
||||||
|
AssertLog.info("定时更新启动...暂停心跳和采集任务");
|
||||||
|
//更改全局变量
|
||||||
|
GlobalConfig.isCollect = false;
|
||||||
|
//调用采集任务
|
||||||
|
agentService.cancelCollect();
|
||||||
//设置检查回滚任务
|
//设置检查回滚任务
|
||||||
String SCRIPT_PATH = properties.getScriptPath()+"/rollback-tragent.sh";
|
String SCRIPT_PATH = properties.getScriptPath()+"/rollback-tragent.sh";
|
||||||
AgentDataUtil.chmod(SCRIPT_PATH,"775");
|
AgentDataUtil.chmod(SCRIPT_PATH,"775");
|
||||||
@@ -113,7 +123,7 @@ public class SpecificTimeTaskService {
|
|||||||
json.put("resMsg", "");
|
json.put("resMsg", "");
|
||||||
json.put("result", jsonObject.toJSONString());
|
json.put("result", jsonObject.toJSONString());
|
||||||
json.put("timestamp",timestamps);
|
json.put("timestamp",timestamps);
|
||||||
Message message = Message.builder().clientId(request.getClientId()).dataType(request.getDataType()).data(jsonObject.toJSONString()).build();
|
Message message = Message.builder().clientId(request.getClientId()).dataType(request.getDataType()).data(json.toJSONString()).build();
|
||||||
if (Objects.nonNull(sessionManager.getSessionById(request.getClientId()))) {
|
if (Objects.nonNull(sessionManager.getSessionById(request.getClientId()))) {
|
||||||
System.out.println("发送执行结果: " + json.toJSONString()); // 注意:toJSONString()
|
System.out.println("发送执行结果: " + json.toJSONString()); // 注意:toJSONString()
|
||||||
sessionManager.writeAndFlush(sessionManager.getSessionById(request.getClientId()).getChannel(), message);
|
sessionManager.writeAndFlush(sessionManager.getSessionById(request.getClientId()).getChannel(), message);
|
||||||
|
|||||||
@@ -36,4 +36,6 @@ public interface AgentService {
|
|||||||
void checkFirewall();
|
void checkFirewall();
|
||||||
|
|
||||||
void checkAndAddFirewallPeriodically();
|
void checkAndAddFirewallPeriodically();
|
||||||
|
|
||||||
|
void checkAgentUpdate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,35 +166,24 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
.clientId(clientId)
|
.clientId(clientId)
|
||||||
.dataType(dataType)
|
.dataType(dataType)
|
||||||
.build();
|
.build();
|
||||||
try {
|
if(StringUtils.equals(dataType, MsgEnum.Agent版本更新应答.getValue())){
|
||||||
taskService.createSpecificTimeTask(request);
|
// 将request对象转换为JSON字符串
|
||||||
JSONObject json = new JSONObject();
|
String jsonContent = "updateMsg=" + JSONObject.toJSONString(request);
|
||||||
json.put("resCode",1);
|
// 检查并创建外置目录
|
||||||
json.put("resMsg", "执行脚本策略定时任务保存成功");
|
if (AdvancedAsyncDownloader.createSingleDirectoryIfNotExists(properties.getConfPath())) {
|
||||||
json.put("timestamp",timestamp);
|
// 将JSON字符串写入文件
|
||||||
// 判定客户端与服务端是否连接
|
AgentUtil.bufferedWriter(properties.getConfPath() + "/agentupdate.conf",
|
||||||
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
new String[]{jsonContent});
|
||||||
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.执行脚本策略应答.getValue())
|
|
||||||
.data(json.toString()).build();
|
|
||||||
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
|
||||||
AssertLog.info("发送执行脚本策略应答={}",JSON.toJSONString(message));
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
JSONObject json = new JSONObject();
|
|
||||||
json.put("resCode",0);
|
|
||||||
json.put("resMsg", "执行脚本策略定时任务保存失败");
|
|
||||||
json.put("timestamp",timestamp);
|
|
||||||
// 判定客户端与服务端是否连接
|
|
||||||
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
|
||||||
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.执行脚本策略应答.getValue())
|
|
||||||
.data(json.toString()).build();
|
|
||||||
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
|
||||||
AssertLog.info("发送执行脚本策略应答={}",JSON.toJSONString(message));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
processCommand(request, timestamp);
|
||||||
}else{
|
}else{
|
||||||
if(StringUtils.equals(dataType, MsgEnum.Agent版本更新应答.getValue())){
|
if(StringUtils.equals(dataType, MsgEnum.Agent版本更新应答.getValue())){
|
||||||
try {
|
try {
|
||||||
|
//更改全局变量
|
||||||
|
GlobalConfig.isCollect = false;
|
||||||
|
//关闭采集任务
|
||||||
|
cancelCollect();
|
||||||
//设置检查回滚任务
|
//设置检查回滚任务
|
||||||
String SCRIPT_PATH = properties.getScriptPath()+"/rollback-tragent.sh";
|
String SCRIPT_PATH = properties.getScriptPath()+"/rollback-tragent.sh";
|
||||||
AgentDataUtil.chmod(SCRIPT_PATH,"775");
|
AgentDataUtil.chmod(SCRIPT_PATH,"775");
|
||||||
@@ -265,6 +254,40 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 辅助方法:持久化定时更新
|
||||||
|
* @param request
|
||||||
|
* @param timestamp
|
||||||
|
*/
|
||||||
|
public void processCommand(SpecificTimeRequest request, long timestamp){
|
||||||
|
try {
|
||||||
|
taskService.createSpecificTimeTask(request);
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put("resCode",1);
|
||||||
|
json.put("resMsg", "执行脚本策略定时任务保存成功");
|
||||||
|
json.put("timestamp",timestamp);
|
||||||
|
// 判定客户端与服务端是否连接
|
||||||
|
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||||
|
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.执行脚本策略应答.getValue())
|
||||||
|
.data(json.toString()).build();
|
||||||
|
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||||
|
AssertLog.info("发送执行脚本策略应答={}",JSON.toJSONString(message));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
JSONObject json = new JSONObject();
|
||||||
|
json.put("resCode",0);
|
||||||
|
json.put("resMsg", "执行脚本策略定时任务保存失败");
|
||||||
|
json.put("timestamp",timestamp);
|
||||||
|
// 判定客户端与服务端是否连接
|
||||||
|
if (Objects.nonNull(sessionManager.getSessionById(GlobalConfig.CLIENT_ID))) {
|
||||||
|
Message message = Message.builder().clientId(GlobalConfig.CLIENT_ID).dataType(MsgEnum.执行脚本策略应答.getValue())
|
||||||
|
.data(json.toString()).build();
|
||||||
|
sessionManager.writeAndFlush(sessionManager.getSessionById(GlobalConfig.CLIENT_ID).getChannel(), message);
|
||||||
|
AssertLog.info("发送执行脚本策略应答={}",JSON.toJSONString(message));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void cancelTask(String taskId) {
|
public void cancelTask(String taskId) {
|
||||||
dynamicTaskService.cancelTask(taskId);
|
dynamicTaskService.cancelTask(taskId);
|
||||||
@@ -288,6 +311,8 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
checkFirewall();
|
checkFirewall();
|
||||||
AssertLog.info("启动检查防火墙策略定时任务 - 延迟: {}ms, 间隔: {}ms", milli, 600000);
|
AssertLog.info("启动检查防火墙策略定时任务 - 延迟: {}ms, 间隔: {}ms", milli, 600000);
|
||||||
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
dynamicTaskService.scheduleTask("checkFirewall", businessTasks::checkFirewallTask, 15000, 600000);
|
||||||
|
AssertLog.info("检测agent更新配置");
|
||||||
|
checkAgentUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -741,9 +766,9 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
if(StringUtils.isNotBlank(md5) && StringUtils.isNotBlank(versionUpdateEO.getFileMd5())
|
if(StringUtils.isNotBlank(md5) && StringUtils.isNotBlank(versionUpdateEO.getFileMd5())
|
||||||
&& StringUtils.equals(md5,versionUpdateEO.getFileMd5())){
|
&& StringUtils.equals(md5,versionUpdateEO.getFileMd5())){
|
||||||
//更改全局变量
|
//更改全局变量
|
||||||
GlobalConfig.isCollect = false;
|
// GlobalConfig.isCollect = false;
|
||||||
//关闭采集任务
|
//关闭采集任务
|
||||||
cancelCollect();
|
// cancelCollect();
|
||||||
//所有文件下载完成,执行脚本命令
|
//所有文件下载完成,执行脚本命令
|
||||||
AssertLog.info("版本策略MD5验证成功");
|
AssertLog.info("版本策略MD5验证成功");
|
||||||
command(policy, GlobalConfig.CLIENT_ID,MsgEnum.Agent版本更新应答.getValue());
|
command(policy, GlobalConfig.CLIENT_ID,MsgEnum.Agent版本更新应答.getValue());
|
||||||
@@ -1460,18 +1485,34 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
if (AdvancedAsyncDownloader.createSingleDirectoryIfNotExists(properties.getConfPath())) {
|
if (AdvancedAsyncDownloader.createSingleDirectoryIfNotExists(properties.getConfPath())) {
|
||||||
AgentUtil.bufferedWriter(properties.getConfPath() + "/businessnetname.conf", lines);
|
AgentUtil.bufferedWriter(properties.getConfPath() + "/businessnetname.conf", lines);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新全局变量
|
// 更新全局变量
|
||||||
GlobalConfig.NETNAME = netName;
|
GlobalConfig.NETNAME = netName;
|
||||||
// 2. 为每个业务网卡执行iptables命令
|
|
||||||
|
// 2. 为每个业务网卡执行iptables命令(先检查规则是否存在)
|
||||||
for (String interfaceName : netNames) {
|
for (String interfaceName : netNames) {
|
||||||
String iface = interfaceName.trim();
|
String iface = interfaceName.trim();
|
||||||
if (!iface.isEmpty()) {
|
if (iface.isEmpty()) {
|
||||||
// 执行IPv4防火墙命令
|
continue;
|
||||||
executeIptablesCommand("iptables", "-I", "INPUT", "1", "-i", iface, "-j", "ACCEPT");
|
}
|
||||||
executeIptablesCommand("iptables", "-I", "OUTPUT", "1", "-o", iface, "-j", "ACCEPT");
|
|
||||||
|
|
||||||
// 执行IPv6防火墙命令
|
// 检查IPv4 INPUT规则是否存在
|
||||||
|
if (!checkRuleExists("iptables", "INPUT", "-i", iface, "-j", "ACCEPT")) {
|
||||||
|
executeIptablesCommand("iptables", "-I", "INPUT", "1", "-i", iface, "-j", "ACCEPT");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查IPv4 OUTPUT规则是否存在
|
||||||
|
if (!checkRuleExists("iptables", "OUTPUT", "-o", iface, "-j", "ACCEPT")) {
|
||||||
|
executeIptablesCommand("iptables", "-I", "OUTPUT", "1", "-o", iface, "-j", "ACCEPT");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查IPv6 INPUT规则是否存在
|
||||||
|
if (!checkRuleExists("ip6tables", "INPUT", "-i", iface, "-j", "ACCEPT")) {
|
||||||
executeIptablesCommand("ip6tables", "-I", "INPUT", "1", "-i", iface, "-j", "ACCEPT");
|
executeIptablesCommand("ip6tables", "-I", "INPUT", "1", "-i", iface, "-j", "ACCEPT");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查IPv6 OUTPUT规则是否存在
|
||||||
|
if (!checkRuleExists("ip6tables", "OUTPUT", "-o", iface, "-j", "ACCEPT")) {
|
||||||
executeIptablesCommand("ip6tables", "-I", "OUTPUT", "1", "-o", iface, "-j", "ACCEPT");
|
executeIptablesCommand("ip6tables", "-I", "OUTPUT", "1", "-o", iface, "-j", "ACCEPT");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1483,6 +1524,7 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行iptables命令
|
* 执行iptables命令
|
||||||
*/
|
*/
|
||||||
@@ -1547,37 +1589,7 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
AssertLog.debug("没有配置业务网卡,跳过防火墙检查");
|
AssertLog.debug("没有配置业务网卡,跳过防火墙检查");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
addFirewall(netName);
|
||||||
String[] netNames = netName.split(";");
|
|
||||||
StringBuilder missingNetNames = new StringBuilder();
|
|
||||||
|
|
||||||
for (String interfaceName : netNames) {
|
|
||||||
String iface = interfaceName.trim();
|
|
||||||
if (iface.isEmpty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查该网卡是否缺少任何规则
|
|
||||||
if (!checkRuleExists("iptables", "INPUT", "-i", iface, "-j", "ACCEPT") ||
|
|
||||||
!checkRuleExists("iptables", "OUTPUT", "-o", iface, "-j", "ACCEPT") ||
|
|
||||||
!checkRuleExists("ip6tables", "INPUT", "-i", iface, "-j", "ACCEPT") ||
|
|
||||||
!checkRuleExists("ip6tables", "OUTPUT", "-o", iface, "-j", "ACCEPT")) {
|
|
||||||
|
|
||||||
if (missingNetNames.length() > 0) {
|
|
||||||
missingNetNames.append(";");
|
|
||||||
}
|
|
||||||
missingNetNames.append(iface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (missingNetNames.length() > 0) {
|
|
||||||
AssertLog.info("检测到以下网卡防火墙策略缺失: {}", missingNetNames.toString());
|
|
||||||
// 只对缺失规则的网卡调用addFirewall
|
|
||||||
addFirewall(missingNetNames.toString());
|
|
||||||
} else {
|
|
||||||
AssertLog.debug("所有业务网卡防火墙策略检查正常,无需添加");
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
AssertLog.error("检查防火墙策略时发生错误: {}", e.getMessage());
|
AssertLog.error("检查防火墙策略时发生错误: {}", e.getMessage());
|
||||||
}
|
}
|
||||||
@@ -1662,4 +1674,29 @@ public class AgentServiceImpl implements AgentService {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkAgentUpdate() {
|
||||||
|
File agentUpdateFile = new File(properties.getConfPath() + "/agentupdate.conf");
|
||||||
|
if (agentUpdateFile.exists()) {
|
||||||
|
Properties props = new Properties();
|
||||||
|
try (InputStream input = Files.newInputStream(agentUpdateFile.toPath())) {
|
||||||
|
props.load(input);
|
||||||
|
|
||||||
|
String updateMsg = props.getProperty("updateMsg");
|
||||||
|
if (StringUtils.isNotBlank(updateMsg)) {
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
timestamp = Math.round(timestamp / 1000.0);
|
||||||
|
SpecificTimeRequest request = JSON.parseObject(updateMsg, SpecificTimeRequest.class);
|
||||||
|
processCommand(request, timestamp);
|
||||||
|
AssertLog.info("应用启动时加载agent更新配置成功: {}", updateMsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
AssertLog.error("应用启动时加载agent更新配置异常", e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
AssertLog.debug("agent更新配置文件不存在: {}", agentUpdateFile.getPath());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import java.util.*;
|
|||||||
@Service
|
@Service
|
||||||
public class NetServiceImpl implements NetService {
|
public class NetServiceImpl implements NetService {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<NetVO> netList(long timestamp) {
|
public List<NetVO> netList(long timestamp) {
|
||||||
List<NetVO> list = new ArrayList<>();
|
List<NetVO> list = new ArrayList<>();
|
||||||
@@ -46,13 +45,21 @@ public class NetServiceImpl implements NetService {
|
|||||||
|
|
||||||
String interfaceName = net.getName();
|
String interfaceName = net.getName();
|
||||||
boolean isBusinessInterface = GlobalConfig.NETNAME.contains(interfaceName);
|
boolean isBusinessInterface = GlobalConfig.NETNAME.contains(interfaceName);
|
||||||
|
String[] ipv6Arr = net.getIPv6addr();
|
||||||
|
String publicIpv6 = "";
|
||||||
|
for (String ipv6 : ipv6Arr) {
|
||||||
|
if(AgentUtil.isPublicIPv6(ipv6)){
|
||||||
|
publicIpv6 = ipv6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
System.out.println("接口名称: " + interfaceName + "(" + net.getDisplayName() + ")");
|
System.out.println("接口名称: " + interfaceName + "(" + net.getDisplayName() + ")");
|
||||||
System.out.println("MAC地址: " + net.getMacaddr());
|
System.out.println("MAC地址: " + net.getMacaddr());
|
||||||
System.out.println("运行状态: " + (net.isConnectorPresent() ? "已连接" : "未连接"));
|
System.out.println("运行状态: " + (net.isConnectorPresent() ? "已连接" : "未连接"));
|
||||||
System.out.println("接口类型: " + AgentUtil.getInterfaceType(net));
|
System.out.println("接口类型: " + AgentUtil.getInterfaceType(net));
|
||||||
System.out.println("IPv4地址: " + String.join(", ", net.getIPv4addr()));
|
System.out.println("IPv4地址: " + String.join(", ", net.getIPv4addr()));
|
||||||
System.out.println("IPv6地址: " + String.join(", ", net.getIPv6addr()));
|
System.out.println("公网IPv6地址: " + publicIpv6);
|
||||||
System.out.println("业务网卡: " + (isBusinessInterface ? "是" : "否"));
|
System.out.println("业务网卡: " + (isBusinessInterface ? "是" : "否"));
|
||||||
|
|
||||||
// 获取总流量
|
// 获取总流量
|
||||||
@@ -98,7 +105,7 @@ public class NetServiceImpl implements NetService {
|
|||||||
.status(net.isConnectorPresent() ? "已连接" : "未连接")
|
.status(net.isConnectorPresent() ? "已连接" : "未连接")
|
||||||
.type(AgentUtil.getInterfaceType(net))
|
.type(AgentUtil.getInterfaceType(net))
|
||||||
.ipV4(String.join(", ", net.getIPv4addr()))
|
.ipV4(String.join(", ", net.getIPv4addr()))
|
||||||
.ipV6(String.join(", ", net.getIPv6addr()))
|
.ipV6(publicIpv6)
|
||||||
.inDropped(net.getInDrops())
|
.inDropped(net.getInDrops())
|
||||||
.outDropped(net.getCollisions())
|
.outDropped(net.getCollisions())
|
||||||
.inSpeed(totalBytesRecv)
|
.inSpeed(totalBytesRecv)
|
||||||
@@ -127,58 +134,51 @@ public class NetServiceImpl implements NetService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取iptables统计信息
|
* 获取iptables统计信息 - 使用命令过滤模式优化
|
||||||
*/
|
*/
|
||||||
private Map<String, Map<String, Long>> getIptablesStatistics() {
|
private Map<String, Map<String, Long>> getIptablesStatistics() {
|
||||||
Map<String, Map<String, Long>> stats = new HashMap<>();
|
Map<String, Map<String, Long>> stats = new HashMap<>();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
System.out.println("开始获取iptables统计信息...");
|
System.out.println("开始获取iptables统计信息(过滤模式)...");
|
||||||
|
|
||||||
|
// 遍历所有业务网卡,为每个网卡分别获取统计信息
|
||||||
|
for (String interfaceName : GlobalConfig.NETNAME.split(";")) {
|
||||||
|
System.out.println("处理业务网卡: " + interfaceName);
|
||||||
|
|
||||||
|
Map<String, Long> interfaceStats = new HashMap<>();
|
||||||
|
|
||||||
// 获取IPv4 INPUT统计
|
// 获取IPv4 INPUT统计
|
||||||
System.out.println("获取IPv4 INPUT统计...");
|
Long ipv4Recv = getIptablesStatForInterface("iptables", "INPUT", interfaceName);
|
||||||
ProcessBuilder pb = new ProcessBuilder("iptables", "-v", "-n", "-x", "-L", "INPUT");
|
if (ipv4Recv != null) {
|
||||||
Process process = pb.start();
|
interfaceStats.put("ipv4Recv", ipv4Recv);
|
||||||
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
||||||
|
|
||||||
String line;
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
parseIptablesLine(line, stats, "ipv4Recv");
|
|
||||||
}
|
}
|
||||||
process.waitFor();
|
|
||||||
|
|
||||||
// 获取IPv4 OUTPUT统计
|
// 获取IPv4 OUTPUT统计
|
||||||
System.out.println("获取IPv4 OUTPUT统计...");
|
Long ipv4Sent = getIptablesStatForInterface("iptables", "OUTPUT", interfaceName);
|
||||||
pb = new ProcessBuilder("iptables", "-v", "-n", "-x", "-L", "OUTPUT");
|
if (ipv4Sent != null) {
|
||||||
process = pb.start();
|
interfaceStats.put("ipv4Sent", ipv4Sent);
|
||||||
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
||||||
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
parseIptablesLine(line, stats, "ipv4Sent");
|
|
||||||
}
|
}
|
||||||
process.waitFor();
|
|
||||||
|
|
||||||
// 获取IPv6 INPUT统计
|
// 获取IPv6 INPUT统计
|
||||||
System.out.println("获取IPv6 INPUT统计...");
|
Long ipv6Recv = getIptablesStatForInterface("ip6tables", "INPUT", interfaceName);
|
||||||
pb = new ProcessBuilder("ip6tables", "-v", "-n", "-x", "-L", "INPUT");
|
if (ipv6Recv != null) {
|
||||||
process = pb.start();
|
interfaceStats.put("ipv6Recv", ipv6Recv);
|
||||||
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
|
||||||
|
|
||||||
while ((line = reader.readLine()) != null) {
|
|
||||||
parseIptablesLine(line, stats, "ipv6Recv");
|
|
||||||
}
|
}
|
||||||
process.waitFor();
|
|
||||||
|
|
||||||
// 获取IPv6 OUTPUT统计
|
// 获取IPv6 OUTPUT统计
|
||||||
System.out.println("获取IPv6 OUTPUT统计...");
|
Long ipv6Sent = getIptablesStatForInterface("ip6tables", "OUTPUT", interfaceName);
|
||||||
pb = new ProcessBuilder("ip6tables", "-v", "-n", "-x", "-L", "OUTPUT");
|
if (ipv6Sent != null) {
|
||||||
process = pb.start();
|
interfaceStats.put("ipv6Sent", ipv6Sent);
|
||||||
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
}
|
||||||
|
|
||||||
while ((line = reader.readLine()) != null) {
|
if (!interfaceStats.isEmpty()) {
|
||||||
parseIptablesLine(line, stats, "ipv6Sent");
|
stats.put(interfaceName, interfaceStats);
|
||||||
|
System.out.println("网卡 " + interfaceName + " 的统计信息: " + interfaceStats);
|
||||||
|
} else {
|
||||||
|
System.out.println("警告: 未找到网卡 " + interfaceName + " 的iptables统计信息");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
process.waitFor();
|
|
||||||
|
|
||||||
System.out.println("最终iptables统计信息: " + stats);
|
System.out.println("最终iptables统计信息: " + stats);
|
||||||
|
|
||||||
@@ -191,63 +191,79 @@ public class NetServiceImpl implements NetService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解析iptables输出行 - 根据实际输出格式修复
|
* 获取指定网卡的iptables统计信息
|
||||||
|
* @param iptablesCmd iptables或ip6tables
|
||||||
|
* @param chain 链名(INPUT/OUTPUT)
|
||||||
|
* @param interfaceName 网卡名
|
||||||
|
* @return 字节数,如果没有找到返回null
|
||||||
*/
|
*/
|
||||||
private void parseIptablesLine(String line, Map<String, Map<String, Long>> stats, String statType) {
|
private Long getIptablesStatForInterface(String iptablesCmd, String chain, String interfaceName) {
|
||||||
|
try {
|
||||||
|
// 构建命令:iptables -v -n -x -L INPUT | grep eth0
|
||||||
|
ProcessBuilder pb = new ProcessBuilder("sh", "-c",
|
||||||
|
iptablesCmd + " -v -n -x -L " + chain + " | grep " + interfaceName);
|
||||||
|
|
||||||
|
Process process = pb.start();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||||
|
|
||||||
|
long totalBytes = 0;
|
||||||
|
String line;
|
||||||
|
boolean found = false;
|
||||||
|
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
System.out.println("解析 " + iptablesCmd + " " + chain + " 行: " + line);
|
||||||
|
Long bytes = parseIptablesLineForInterface(line);
|
||||||
|
if (bytes != null) {
|
||||||
|
totalBytes += bytes;
|
||||||
|
found = true;
|
||||||
|
System.out.println("找到匹配的规则: " + bytes + " bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
process.waitFor();
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
System.out.println(iptablesCmd + " " + chain + " 接口 " + interfaceName + " 总流量: " + totalBytes + " bytes");
|
||||||
|
return totalBytes;
|
||||||
|
} else {
|
||||||
|
System.out.println("未找到 " + iptablesCmd + " " + chain + " 接口 " + interfaceName + " 的统计信息");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("获取 " + iptablesCmd + " " + chain + " 统计失败: " + e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析iptables输出行
|
||||||
|
*/
|
||||||
|
private Long parseIptablesLineForInterface(String line) {
|
||||||
line = line.trim();
|
line = line.trim();
|
||||||
|
|
||||||
if (line.isEmpty() || line.startsWith("Chain") || line.startsWith("pkts") || line.startsWith("target")) {
|
if (line.isEmpty() || line.startsWith("Chain") || line.startsWith("pkts") || line.startsWith("target")) {
|
||||||
return;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 使用空格分割,处理多个连续空格
|
// 使用空格分割,处理多个连续空格
|
||||||
String[] parts = line.split("\\s+");
|
String[] parts = line.split("\\s+");
|
||||||
System.out.println("解析行: " + line);
|
|
||||||
System.out.println("分割部分数量: " + parts.length + ", 内容: " + Arrays.toString(parts));
|
|
||||||
|
|
||||||
if (parts.length >= 7) {
|
if (parts.length >= 7) {
|
||||||
try {
|
try {
|
||||||
// 字节数在第二列(索引1)
|
// 字节数在第二列(索引1)
|
||||||
long bytes = Long.parseLong(parts[1]);
|
long bytes = Long.parseLong(parts[1]);
|
||||||
String interfaceName = null;
|
|
||||||
|
|
||||||
// 根据statType确定是输入接口还是输出接口
|
// 由于已经用grep过滤了,直接返回字节数
|
||||||
if ("ipv4Recv".equals(statType) || "ipv6Recv".equals(statType)) {
|
System.out.println("找到匹配的规则: " + bytes + " bytes");
|
||||||
// 接收流量:查看输入接口(第6列,索引5)
|
return bytes;
|
||||||
if (parts.length > 5 && !parts[5].equals("*")) {
|
|
||||||
interfaceName = parts[5];
|
|
||||||
System.out.println("接收流量 - 输入接口: " + interfaceName);
|
|
||||||
}
|
|
||||||
} else if ("ipv4Sent".equals(statType) || "ipv6Sent".equals(statType)) {
|
|
||||||
// 发送流量:查看输出接口(第7列,索引6)
|
|
||||||
if (parts.length > 6 && !parts[6].equals("*")) {
|
|
||||||
interfaceName = parts[6];
|
|
||||||
System.out.println("发送流量 - 输出接口: " + interfaceName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (interfaceName != null && GlobalConfig.NETNAME.contains(interfaceName)) {
|
|
||||||
Map<String, Long> interfaceStats = stats.getOrDefault(interfaceName, new HashMap<>());
|
|
||||||
|
|
||||||
// 累加相同接口的流量(处理多条规则匹配同一接口的情况)
|
|
||||||
long currentBytes = interfaceStats.getOrDefault(statType, 0L);
|
|
||||||
interfaceStats.put(statType, currentBytes + bytes);
|
|
||||||
stats.put(interfaceName, interfaceStats);
|
|
||||||
|
|
||||||
System.out.println("成功记录iptables统计: " + interfaceName + " - " + statType + " = " + bytes + " bytes (累计: " + (currentBytes + bytes) + ")");
|
|
||||||
} else if (interfaceName != null) {
|
|
||||||
System.out.println("接口 " + interfaceName + " 不是业务网卡,跳过");
|
|
||||||
} else {
|
|
||||||
System.out.println("未找到有效的接口名(可能是通配符*)");
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
System.err.println("解析iptables行失败,无法解析数字: " + line);
|
System.err.println("解析iptables行失败,无法解析数字: " + line);
|
||||||
System.err.println("错误部分: " + parts[1]);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
System.out.println("行格式不符合预期,跳过: " + line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, String> getNetworkMode(String interfaceName) {
|
public static Map<String, String> getNetworkMode(String interfaceName) {
|
||||||
|
|||||||
@@ -814,7 +814,140 @@ public class AgentUtil {
|
|||||||
int hz = getSystemHz();
|
int hz = getSystemHz();
|
||||||
return (double) ticks / hz;
|
return (double) ticks / hz;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* 判断IPv6地址是否为公网地址
|
||||||
|
* @param ipv6 IPv6地址字符串
|
||||||
|
* @return true-公网地址, false-私网地址或无效地址
|
||||||
|
*/
|
||||||
|
public static boolean isPublicIPv6(String ipv6) {
|
||||||
|
if (ipv6 == null || ipv6.trim().isEmpty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 规范化IPv6地址(处理缩写形式)
|
||||||
|
String normalized = normalizeIPv6(ipv6);
|
||||||
|
if (normalized == null) {
|
||||||
|
return false; // 无效的IPv6地址
|
||||||
|
}
|
||||||
|
|
||||||
|
// 私网地址范围:
|
||||||
|
// 1. fc00::/7 - 唯一本地地址 (ULA)
|
||||||
|
// 2. fe80::/10 - 链路本地地址
|
||||||
|
// 3. ::1/128 - 环回地址
|
||||||
|
// 4. ::/128 - 未指定地址
|
||||||
|
|
||||||
|
if (normalized.startsWith("fc") || normalized.startsWith("fd")) {
|
||||||
|
return false; // fc00::/7 (ULA)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalized.startsWith("fe8") || normalized.startsWith("fe9") ||
|
||||||
|
normalized.startsWith("fea") || normalized.startsWith("feb")) {
|
||||||
|
return false; // fe80::/10 (链路本地)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalized.equals("00000000000000000000000000000001") ||
|
||||||
|
normalized.equals("00000000000000000000000000000000")) {
|
||||||
|
return false; // ::1 和 ::
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
return false; // 解析异常,视为无效地址
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 规范化IPv6地址为完整的32字符十六进制形式(无冒号)
|
||||||
|
*/
|
||||||
|
private static String normalizeIPv6(String ipv6) {
|
||||||
|
// 处理环回和未指定地址的特殊情况
|
||||||
|
if ("::1".equals(ipv6) || "::".equals(ipv6)) {
|
||||||
|
return ipv6.equals("::1") ?
|
||||||
|
"00000000000000000000000000000001" :
|
||||||
|
"00000000000000000000000000000000";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分离可能的IPv6字面量(如[::1]形式)
|
||||||
|
ipv6 = ipv6.replaceAll("[\\[\\]]", "");
|
||||||
|
|
||||||
|
// 分离地址和端口(如果有)
|
||||||
|
String[] parts = ipv6.split("%", 2); // 处理区域标识符
|
||||||
|
String address = parts[0];
|
||||||
|
|
||||||
|
// 分离IPv4映射的IPv6地址(如::ffff:192.168.1.1)
|
||||||
|
if (address.contains(".")) {
|
||||||
|
if (address.startsWith("::ffff:")) {
|
||||||
|
// IPv4映射地址,暂时按公网处理或根据需求调整
|
||||||
|
return "00000000000000000000000000000000"; // 这里可根据需要调整
|
||||||
|
}
|
||||||
|
return null; // 无效的混合格式
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否为缩写形式并扩展
|
||||||
|
if (address.contains("::")) {
|
||||||
|
address = expandDoubleColon(address);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 分割成8个16位块
|
||||||
|
String[] blocks = address.split(":");
|
||||||
|
if (blocks.length != 8) {
|
||||||
|
return null; // 无效的IPv6格式
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将每个块扩展为4个十六进制字符
|
||||||
|
StringBuilder normalized = new StringBuilder(32);
|
||||||
|
for (String block : blocks) {
|
||||||
|
if (block.length() > 4) {
|
||||||
|
return null; // 无效的块长度
|
||||||
|
}
|
||||||
|
// 左侧补零到4位
|
||||||
|
String padded = "0000" + block;
|
||||||
|
normalized.append(padded.substring(padded.length() - 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalized.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 扩展双冒号缩写
|
||||||
|
*/
|
||||||
|
private static String expandDoubleColon(String ipv6) {
|
||||||
|
int doubleColonIndex = ipv6.indexOf("::");
|
||||||
|
String[] parts = ipv6.split("::", -1);
|
||||||
|
|
||||||
|
if (parts.length != 2) {
|
||||||
|
return ipv6; // 无效的双冒号格式
|
||||||
|
}
|
||||||
|
|
||||||
|
String leftPart = parts[0];
|
||||||
|
String rightPart = parts[1];
|
||||||
|
|
||||||
|
int leftCount = leftPart.isEmpty() ? 0 : leftPart.split(":").length;
|
||||||
|
int rightCount = rightPart.isEmpty() ? 0 : rightPart.split(":").length;
|
||||||
|
int zeroCount = 8 - (leftCount + rightCount);
|
||||||
|
|
||||||
|
if (zeroCount <= 0) {
|
||||||
|
return ipv6; // 无效的缩写
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder zeros = new StringBuilder();
|
||||||
|
for (int i = 0; i < zeroCount; i++) {
|
||||||
|
if (i > 0) zeros.append(":");
|
||||||
|
zeros.append("0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (leftPart.isEmpty() && rightPart.isEmpty()) {
|
||||||
|
return zeros.toString();
|
||||||
|
} else if (leftPart.isEmpty()) {
|
||||||
|
return zeros + ":" + rightPart;
|
||||||
|
} else if (rightPart.isEmpty()) {
|
||||||
|
return leftPart + ":" + zeros;
|
||||||
|
} else {
|
||||||
|
return leftPart + ":" + zeros + ":" + rightPart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user