summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorshizhendong <[email protected]>2022-04-02 15:15:17 +0800
committershizhendong <[email protected]>2022-04-02 15:15:17 +0800
commitc5b0bfc33785617a801ebbf6292ecd6199363cdd (patch)
tree927235f65e117021df796bdf904012f27ea1212b /src
parentb6f059255b8ac6c8200d15ab79697097f43fd7c0 (diff)
feat: NEZ-1746 agent 增加 ping,traceroute 命令执行接口
Diffstat (limited to 'src')
-rw-r--r--src/main/java/net/geedge/confagent/controller/PingController.java176
-rw-r--r--src/main/java/net/geedge/confagent/controller/TracerouteController.java125
-rw-r--r--src/main/java/net/geedge/confagent/entity/PingEntity.java44
-rw-r--r--src/main/java/net/geedge/confagent/util/CommonUtils.java320
-rw-r--r--src/main/java/net/geedge/confagent/util/Tool.java53
5 files changed, 713 insertions, 5 deletions
diff --git a/src/main/java/net/geedge/confagent/controller/PingController.java b/src/main/java/net/geedge/confagent/controller/PingController.java
new file mode 100644
index 0000000..1960111
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/controller/PingController.java
@@ -0,0 +1,176 @@
+package net.geedge.confagent.controller;
+
+import cn.hutool.core.lang.Pair;
+import cn.hutool.core.thread.ThreadFactoryBuilder;
+import cn.hutool.core.util.ReUtil;
+import cn.hutool.log.Log;
+import net.geedge.confagent.entity.PingEntity;
+import net.geedge.confagent.util.CommonUtils;
+import net.geedge.confagent.util.R;
+import net.geedge.confagent.util.Tool;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.net.UnknownHostException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.*;
+import java.util.regex.Pattern;
+
+@RestController
+@RequestMapping("/cmd")
+public class PingController {
+
+ private final static Log log = Log.get();
+
+ static Integer defaultCorePoolSize = 10;
+
+ static ThreadPoolExecutor execPingThreadPoolExecutor;
+
+ // windows ipv4/6 匹配 最短 = 3ms,最长 = 6ms,平均 = 4ms
+ static Pattern WinPingStatRegex = Pattern.compile("(.{2} = \\d+ms)");
+ // windows ipv4/6 匹配 25% 丢失
+ static Pattern WinPingRateRegex = Pattern.compile("\\d+(\\.\\d+)?% 丢失");
+ // linux ipv4/6 匹配 rtt min/avg/max/mdev = 0.788/1.296/1.627/0.319 ms
+ static Pattern LinuxPingStatRegex = Pattern.compile("(min/avg/max.*=.*ms)");
+ // linux ipv4/6 匹配 25% packet loss
+ static Pattern LinuxPingRateRegex = Pattern.compile("\\d+(\\.\\d+)?% packet loss");
+
+ static {
+ execPingThreadPoolExecutor = new ThreadPoolExecutor(defaultCorePoolSize, Integer.MAX_VALUE,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>(), new ThreadFactoryBuilder().setNamePrefix("ping-pool-").build());
+ }
+
+ @PostMapping("/ping")
+ public R ping(@RequestBody PingEntity pingEntity) throws UnknownHostException {
+ Integer packetsize = Tool.ObjectUtil.defaultIfNull(pingEntity.getPacketsize(), 64);
+ Integer count = Tool.ObjectUtil.defaultIfNull(pingEntity.getCount(), 4);
+ Integer timeout = Tool.ObjectUtil.defaultIfNull(pingEntity.getTimeout(), 100);
+ Integer concurrent = Tool.ObjectUtil.defaultIfNull(pingEntity.getConcurrent(), 10);
+
+ List<Callable<Map<String, Object>>> taskList = Tool.ListUtil.list(false);
+
+ // 获取本地 IP 当作 source ip
+ String sourceIp = Tool.InetAddressUtil.getLocalHostLANAddress();
+ List<String> ips = pingEntity.getIps();
+
+ for (String ip : ips) {
+ if (CommonUtils.isLinux()) {
+ String pingCmd = null;
+ if (CommonUtils.checkIpv4(ip)) {
+ pingCmd = String.format("ping -c %s -s %s -W %s %s", count, packetsize, (double) timeout / 1000, ip);
+ } else if (CommonUtils.checkIpv6(ip)) {
+ pingCmd = String.format("ping -6 -c %s -s %s -W %s %s", count, packetsize, (double) timeout / 1000, ip);
+ } else {
+ // 都没有匹配就执行IPV4
+ pingCmd = String.format("ping -c %s -s %s -W %s %s", count, packetsize, (double) timeout / 1000, ip);
+ }
+ log.info("ping cmd : {}", pingCmd);
+ Callable<Map<String, Object>> callable = this.getLinuxPingCallable(ip, pingCmd, sourceIp);
+ taskList.add(callable);
+ } else if (CommonUtils.isWindows()) {
+ String pingCmd = null;
+ if (CommonUtils.checkIpv4(ip)) {
+ pingCmd = String.format("ping -n %s -l %s -w %s %s", count, packetsize, timeout, ip);
+ } else if (CommonUtils.checkIpv6(ip)) {
+ pingCmd = String.format("ping -6 -n %s -l %s -w %s %s", count, packetsize, timeout, ip);
+ } else {
+ // 都没有匹配就执行IPV4
+ pingCmd = String.format("ping -n %s -l %s -w %s %s", count, packetsize, timeout, ip);
+ }
+ log.info("ping cmd : {}", pingCmd);
+ Callable<Map<String, Object>> callable = this.getWinPingCallable(ip, pingCmd, sourceIp);
+ taskList.add(callable);
+ }
+ }
+
+ List<Map<String, Object>> result = Tool.ListUtil.list(false);
+ boolean b = false;
+ try {
+ if (concurrent > execPingThreadPoolExecutor.getCorePoolSize()) {
+ // 修改线程池核心线程数
+ execPingThreadPoolExecutor.setCorePoolSize(concurrent);
+ b = true;
+ }
+ List<Future<Map<String, Object>>> futures = ((ExecutorService) execPingThreadPoolExecutor).invokeAll(taskList);
+ for (Future<Map<String, Object>> future : futures) {
+ if (!future.isCancelled()) {
+ Map<String, Object> map = future.get();
+ result.add(map);
+ }
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ log.error(e);
+ } finally {
+ // 如果修改了核心线程数 ,本次执行后恢复初始数量
+ if (b) execPingThreadPoolExecutor.setCorePoolSize(defaultCorePoolSize);
+ }
+
+ return R.ok().put("data", Tool.MapUtil.of(Pair.of("list", result)));
+ }
+
+ private Callable<Map<String, Object>> getWinPingCallable(String ip, String pingCmd, String sourceIp) {
+ Callable<Map<String, Object>> callable = () -> {
+ Map<String, Object> stat = Tool.MapUtil.newHashMap();
+ String forStr = Tool.RuntimeUtil.execForStr(pingCmd);
+ List<String> stringList = ReUtil.findAllGroup0(WinPingStatRegex, forStr);
+ if (Tool.CollectionUtil.isEmpty(stringList)) {
+ stat.put("min", 0);
+ stat.put("max", 0);
+ stat.put("avg", 0);
+ // 没有匹配到 min max avg 数据,证明百分百丢包 windows 如果ping 全部失败返回为 0 ,这里不取他返回的数据,全部失败丢包率为 100%
+ stat.put("rate", 100);
+ stat.put("state", 0);
+ } else {
+ stat.put("min", ReUtil.getFirstNumber(stringList.get(0)));
+ stat.put("max", ReUtil.getFirstNumber(stringList.get(1)));
+ stat.put("avg", ReUtil.getFirstNumber(stringList.get(2)));
+ String rateStr = ReUtil.getGroup0(WinPingRateRegex, forStr);
+ Double rateDoubleValue = Double.valueOf(rateStr.split("%")[0]);
+ stat.put("rate", rateDoubleValue);
+ // 丢包率为0,state = up 否则为 error
+ stat.put("state", rateDoubleValue == 0 ? 1 : 2);
+ }
+ stat.put("raw", forStr);
+ stat.put("ip", ip);
+ stat.put("source", sourceIp);
+ return stat;
+ };
+ return callable;
+ }
+
+ private Callable<Map<String, Object>> getLinuxPingCallable(String ip, String pingCmd, String sourceIp) {
+ Callable<Map<String, Object>> callable = () -> {
+ Map<String, Object> stat = Tool.MapUtil.newHashMap();
+ String forStr = Tool.RuntimeUtil.execForStr(pingCmd);
+ String group0 = ReUtil.getGroup0(LinuxPingStatRegex, forStr);
+ if (Tool.StrUtil.isEmpty(group0)) {
+ stat.put("min", 0);
+ stat.put("max", 0);
+ stat.put("avg", 0);
+ stat.put("rate", 100);
+ stat.put("state", 0);
+ } else {
+ List<String> strings = Arrays.asList(group0.split("="));
+ List<String> minAvgMaxList = Arrays.asList(strings.get(1).trim().split("/"));
+ stat.put("min", Double.valueOf(minAvgMaxList.get(0)));
+ stat.put("max", Double.valueOf(minAvgMaxList.get(2)));
+ stat.put("avg", Double.valueOf(minAvgMaxList.get(1)));
+ String rateStr = ReUtil.getGroup0(LinuxPingRateRegex, forStr);
+ Double rateDoubleValue = Double.valueOf(rateStr.split("%")[0]);
+ // 丢包率为0,state = up 否则为 error
+ stat.put("state", rateDoubleValue == 0 ? 1 : 2);
+ }
+
+ stat.put("raw", forStr);
+ stat.put("ip", ip);
+ stat.put("source", sourceIp);
+ return stat;
+ };
+ return callable;
+ }
+}
diff --git a/src/main/java/net/geedge/confagent/controller/TracerouteController.java b/src/main/java/net/geedge/confagent/controller/TracerouteController.java
new file mode 100644
index 0000000..0b8a561
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/controller/TracerouteController.java
@@ -0,0 +1,125 @@
+package net.geedge.confagent.controller;
+
+import cn.hutool.core.date.TimeInterval;
+import cn.hutool.core.lang.Pair;
+import cn.hutool.core.thread.ThreadFactoryBuilder;
+import cn.hutool.log.Log;
+import net.geedge.confagent.entity.PingEntity;
+import net.geedge.confagent.util.CommonUtils;
+import net.geedge.confagent.util.R;
+import net.geedge.confagent.util.Tool;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.*;
+
+@RestController
+@RequestMapping("/cmd")
+public class TracerouteController {
+
+ private final static Log log = Log.get();
+
+ static Integer defaultCorePoolSize = 10;
+
+ static ThreadPoolExecutor execTracerouteThreadPoolExecutor;
+
+ static {
+ execTracerouteThreadPoolExecutor = new ThreadPoolExecutor(defaultCorePoolSize, Integer.MAX_VALUE,
+ 0L, TimeUnit.MILLISECONDS,
+ new LinkedBlockingQueue<Runnable>(), new ThreadFactoryBuilder().setNamePrefix("traceroute-pool-").build());
+ }
+
+ @PostMapping("/traceroute")
+ public R traceroute(@RequestBody PingEntity pingEntity) throws UnknownHostException {
+ // Linux 可以指定 package size ,win 不行
+ Integer packetsize = Tool.ObjectUtil.defaultIfNull(pingEntity.getPacketsize(), 64);
+ Integer maxHops = Tool.ObjectUtil.defaultIfNull(pingEntity.getMaxHops(), 10);
+ // win 单位 ms,,linux 单位 s,(支持浮点数)
+ Integer timeout = Tool.ObjectUtil.defaultIfNull(pingEntity.getTimeout(), 100);
+ Integer concurrent = Tool.ObjectUtil.defaultIfNull(pingEntity.getConcurrent(), 10);
+
+ List<Callable<Map<String, Object>>> taskList = Tool.ListUtil.list(false);
+
+ // 获取本地 IP 当作 source ip
+ String sourceIp = Tool.InetAddressUtil.getLocalHostLANAddress();
+
+ List<String> ips = pingEntity.getIps();
+ for (String ip : ips) {
+ if (CommonUtils.isLinux()) {
+ String tracerouteCmd = null;
+ if (CommonUtils.checkIpv4(ip)) {
+ tracerouteCmd = String.format("traceroute -4 -m %s -w %s %s %s", maxHops, (double) timeout / 1000, ip, packetsize);
+ } else if (CommonUtils.checkIpv6(ip)) {
+ tracerouteCmd = String.format("traceroute -6 -m %s -w %s %s %s", maxHops, (double) timeout / 1000, ip, packetsize);
+ } else {
+ // 都没有匹配就执行IPV4
+ tracerouteCmd = String.format("traceroute -4 -m %s -w %s %s %s", maxHops, (double) timeout / 1000, ip, packetsize);
+ }
+ log.info("traceroute cmd : {}", tracerouteCmd);
+ Callable<Map<String, Object>> callable = this.getTracerouteCallable(ip, tracerouteCmd, sourceIp);
+ taskList.add(callable);
+ } else if (CommonUtils.isWindows()) {
+ String tracerouteCmd = null;
+ if (CommonUtils.checkIpv4(ip)) {
+ tracerouteCmd = String.format("tracert -4 -h %s -w %s %s", maxHops, timeout, ip);
+ } else if (CommonUtils.checkIpv6(ip)) {
+ tracerouteCmd = String.format("tracert -6 -h %s -w %s %s", maxHops, timeout, ip);
+ } else {
+ // 都没有匹配就执行IPV4
+ tracerouteCmd = String.format("tracert -4 -h %s -w %s %s", maxHops, timeout, ip);
+ }
+ log.info("traceroute cmd : {}", tracerouteCmd);
+ Callable<Map<String, Object>> callable = this.getTracerouteCallable(ip, tracerouteCmd, sourceIp);
+ taskList.add(callable);
+ }
+ }
+
+ List<Map<String, Object>> result = Tool.ListUtil.list(false);
+ boolean b = false;
+ try {
+ if (concurrent > execTracerouteThreadPoolExecutor.getCorePoolSize()) {
+ // 修改线程池核心线程数
+ execTracerouteThreadPoolExecutor.setCorePoolSize(concurrent);
+ b = true;
+ }
+ List<Future<Map<String, Object>>> futures = ((ExecutorService) execTracerouteThreadPoolExecutor).invokeAll(taskList);
+ for (Future<Map<String, Object>> future : futures) {
+ if (!future.isCancelled()) {
+ Map<String, Object> map = future.get();
+ result.add(map);
+ }
+ }
+ } catch (InterruptedException | ExecutionException e) {
+ log.error(e);
+ } finally {
+ // 如果修改了核心线程数 ,本次执行后恢复初始数量
+ if (b) execTracerouteThreadPoolExecutor.setCorePoolSize(defaultCorePoolSize);
+ }
+
+ return R.ok().put("data", Tool.MapUtil.of(Pair.of("list", result)));
+ }
+
+ private Callable<Map<String, Object>> getTracerouteCallable(String ip, String tracerouteCmd, String sourceIp) {
+ Callable<Map<String, Object>> callable = () -> {
+ Map<String, Object> stat = Tool.MapUtil.newHashMap();
+ TimeInterval timer = Tool.DateUtil.timer();
+ Process process = Tool.RuntimeUtil.exec(tracerouteCmd);
+ String result = Tool.RuntimeUtil.getResult(process);
+ stat.put("time", timer.interval());
+ // {0} indicates normal termination.
+ int i = process.waitFor();
+ stat.put("state", i == 0 ? 1 : 0);
+ stat.put("raw", result);
+ stat.put("ip", ip);
+ stat.put("source", sourceIp);
+ return stat;
+ };
+ return callable;
+ }
+
+}
diff --git a/src/main/java/net/geedge/confagent/entity/PingEntity.java b/src/main/java/net/geedge/confagent/entity/PingEntity.java
new file mode 100644
index 0000000..5a105a4
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/entity/PingEntity.java
@@ -0,0 +1,44 @@
+package net.geedge.confagent.entity;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+@Data
+public class PingEntity implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+ /**
+ * ip地址
+ */
+ private List<String> ips;
+
+ /**
+ * 包大小
+ * 默认:64
+ */
+ private Integer packetsize;
+
+ /**
+ * 执行次数
+ * 默认:4
+ */
+ private Integer count;
+
+ /**
+ * 超时时间
+ * 默认:10s
+ */
+ private Integer timeout;
+
+ /**
+ * 并发线程数量,默认:10
+ */
+ private Integer concurrent;
+
+ /**
+ * maxHops
+ */
+ private Integer maxHops;
+}
diff --git a/src/main/java/net/geedge/confagent/util/CommonUtils.java b/src/main/java/net/geedge/confagent/util/CommonUtils.java
new file mode 100644
index 0000000..65e2cef
--- /dev/null
+++ b/src/main/java/net/geedge/confagent/util/CommonUtils.java
@@ -0,0 +1,320 @@
+package net.geedge.confagent.util;
+
+import cn.hutool.core.net.NetUtil;
+
+import java.io.File;
+import java.net.URL;
+import java.util.*;
+import java.util.regex.Pattern;
+
+/**
+ * 公用方法工具类
+ */
+public class CommonUtils {
+ private static String OS = System.getProperty("os.name").toLowerCase();
+
+ /**
+ * 非空判断
+ *
+ * @param objs 要判断,处理的对象
+ * @return Boolean
+ * @author <a href="mailto:[email protected]">Ben</a>
+ * @see <b>对象为Null返回true,集合的大小为0也返回true,迭代器没有下一个也返回true..</b>
+ * @since 1.0
+ */
+ public static Boolean isEmpty(Object... objs) {
+
+ if (objs == null) {
+ return Boolean.TRUE;
+ }
+
+ if (objs.length == 0) return Boolean.TRUE;
+
+ for (Object obj : objs) {
+ if (obj == null) {
+ return true;
+ }
+
+ // 字符序列集
+ if ((obj instanceof CharSequence) && "".equals(obj.toString().trim())) {
+ return true;
+ }
+ // 单列集合
+ if (obj instanceof Collection) {
+ if (((Collection<?>) obj).isEmpty()) {
+ return true;
+ }
+ }
+ // 双列集合
+ if (obj instanceof Map) {
+ if (((Map<?, ?>) obj).isEmpty()) {
+ return true;
+ }
+ }
+ if (obj instanceof Iterable) {
+ if (((Iterable<?>) obj).iterator() == null || !((Iterable<?>) obj).iterator().hasNext()) {
+ return true;
+ }
+ }
+ // 迭代器
+ if (obj instanceof Iterator) {
+ if (!((Iterator<?>) obj).hasNext()) {
+ return true;
+ }
+ }
+ // 文件类型
+ if (obj instanceof File) {
+ if (!((File) obj).exists()) {
+ return true;
+ }
+ }
+ if ((obj instanceof Object[]) && ((Object[]) obj).length == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 空判断
+ *
+ * @param obj 要判断,处理的对象
+ * @return Boolean
+ * @author <a href="mailto:[email protected]">Ben</a>
+ * @see <b>与非空相反</b>
+ * @since 1.0
+ */
+ public static Boolean notEmpty(Object... obj) {
+ return !isEmpty(obj);
+ }
+
+
+ public static <A, E extends A> A[] toArray(Enumeration<E> enumeration, A[] array) {
+ ArrayList<A> elements = new ArrayList<A>();
+ while (enumeration.hasMoreElements()) {
+ elements.add(enumeration.nextElement());
+ }
+ return elements.toArray(array);
+ }
+
+ /**
+ * @Description 根据相对路径获取根目录下的文件
+ * @Date 2021/4/23
+ */
+ public static File getResourceFile(String path) {
+ File file = Tool.FileUtil.newFile(path);
+ if (file.exists()) {
+ return file;
+ } else {
+ URL resource = CommonUtils.class.getClassLoader().getResource(path);
+ return resource == null ? null : Tool.FileUtil.newFile(resource.getFile());
+ }
+ }
+
+ public static boolean isLinux() {
+ return OS.indexOf("linux") >= 0;
+ }
+
+ public static boolean isMacOS() {
+ return OS.indexOf("mac") >= 0 && OS.indexOf("os") > 0 && OS.indexOf("x") < 0;
+ }
+
+ public static boolean isMacOSX() {
+ return OS.indexOf("mac") >= 0 && OS.indexOf("os") > 0 && OS.indexOf("x") > 0;
+ }
+
+ public static boolean isWindows() {
+ return OS.indexOf("windows") >= 0;
+ }
+
+ public static boolean isOS2() {
+ return OS.indexOf("os/2") >= 0;
+ }
+
+ public static boolean isSolaris() {
+ return OS.indexOf("solaris") >= 0;
+ }
+
+ public static boolean isSunOS() {
+ return OS.indexOf("sunos") >= 0;
+ }
+
+ public static boolean isMPEiX() {
+ return OS.indexOf("mpe/ix") >= 0;
+ }
+
+ public static boolean isHPUX() {
+ return OS.indexOf("hp-ux") >= 0;
+ }
+
+ public static boolean isAix() {
+ return OS.indexOf("aix") >= 0;
+ }
+
+ public static boolean isOS390() {
+ return OS.indexOf("os/390") >= 0;
+ }
+
+ public static boolean isFreeBSD() {
+ return OS.indexOf("freebsd") >= 0;
+ }
+
+ public static boolean isIrix() {
+ return OS.indexOf("irix") >= 0;
+ }
+
+ public static boolean isDigitalUnix() {
+ return OS.indexOf("digital") >= 0 && OS.indexOf("unix") > 0;
+ }
+
+ public static boolean isNetWare() {
+ return OS.indexOf("netware") >= 0;
+ }
+
+ public static boolean isOSF1() {
+ return OS.indexOf("osf1") >= 0;
+ }
+
+ public static boolean isOpenVMS() {
+ return OS.indexOf("openvms") >= 0;
+ }
+
+ public static boolean isUnix() {
+ boolean isUnix = isLinux();
+ if (!isUnix) {
+ isUnix = isMacOS();
+ }
+ if (!isUnix) {
+ isUnix = isMacOSX();
+ }
+ if (!isUnix) {
+ isUnix = isLinux();
+ }
+ if (!isUnix) {
+ isUnix = isDigitalUnix();
+ }
+ if (!isUnix) {
+ isUnix = isAix();
+ }
+ if (!isUnix) {
+ isUnix = isFreeBSD();
+ }
+ if (!isUnix) {
+ isUnix = isHPUX();
+ }
+ if (!isUnix) {
+ isUnix = isIrix();
+ }
+ if (!isUnix) {
+ isUnix = isMPEiX();
+ }
+ if (!isUnix) {
+ isUnix = isNetWare();
+ }
+ if (!isUnix) {
+ isUnix = isOpenVMS();
+ }
+ if (!isUnix) {
+ isUnix = isOS2();
+ }
+ if (!isUnix) {
+ isUnix = isOS390();
+ }
+ if (!isUnix) {
+ isUnix = isOSF1();
+ }
+ if (!isUnix) {
+ isUnix = isSunOS();
+ }
+ if (!isUnix) {
+ isUnix = isSolaris();
+ }
+ return isUnix;
+ }
+
+ /**
+ * linux内核平台 1
+ * window: 2
+ * 其他平台 0
+ */
+ public static int getPlatform() {
+ int platform = 0;
+ if (CommonUtils.isUnix()) {
+ platform = 1;
+ }
+ if (CommonUtils.isWindows()) {
+ platform = 2;
+ }
+ return platform;
+ }
+
+ public static String uuid() {
+ return UUID.randomUUID().toString().replaceAll("-", "");
+ }
+
+ /**
+ * 生成指定长度的uuid
+ *
+ * @param len
+ * @return
+ */
+ public static String uuid(int len) {
+ StringBuffer sb = new StringBuffer();
+ while (sb.length() < len) {
+ sb.append(uuid());
+ }
+ return sb.toString().substring(0, len);
+ }
+
+ /**
+ * 获取本机所有网卡IP
+ *
+ * @return
+ */
+ public static Set<String> getInetIpAddress() {
+ return NetUtil.localIpv4s();
+ }
+
+
+ /**
+ * 端口合法性校验
+ *
+ * @param port
+ * @return
+ */
+ public static boolean checkPort(String port) {
+ String regex = "^[1-9][0-9]{0,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]{1}|6553[0-5]$";
+ boolean flag = Pattern.matches(regex, port.toString());
+ return flag;
+ }
+
+ public static boolean checkIp(String ip) {
+ Pattern ipv6Check = Pattern.compile("^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:)|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}){1,2})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){1,3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){1,4})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){1,5})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){1,6})|(:(:[0-9A-Fa-f]{1,4}){1,7})|(([0-9A-Fa-f]{1,4}:){6}(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){0,4}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(:(:[0-9A-Fa-f]{1,4}){0,5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}))$");
+ Pattern ipv4Check = Pattern.compile("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$");
+ boolean ipv6Result = ipv6Check.matcher(ip).matches();
+ boolean ipv4Result = ipv4Check.matcher(ip).matches();
+ if (!(ipv6Result || ipv4Result)) {
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean checkIpv4(String ip) {
+ Pattern ipv4Check = Pattern.compile("^(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}$");
+ boolean ipv4Result = ipv4Check.matcher(ip).matches();
+ if (!ipv4Result) {
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean checkIpv6(String ip) {
+ Pattern ipv6Check = Pattern.compile("^((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:)|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}(:[0-9A-Fa-f]{1,4}){1,2})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){1,3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){1,4})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){1,5})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){1,6})|(:(:[0-9A-Fa-f]{1,4}){1,7})|(([0-9A-Fa-f]{1,4}:){6}(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){4}(:[0-9A-Fa-f]{1,4}){0,1}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){3}(:[0-9A-Fa-f]{1,4}){0,2}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(([0-9A-Fa-f]{1,4}:){2}(:[0-9A-Fa-f]{1,4}){0,3}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|([0-9A-Fa-f]{1,4}:(:[0-9A-Fa-f]{1,4}){0,4}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3})|(:(:[0-9A-Fa-f]{1,4}){0,5}:(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}))$");
+ boolean ipv6Result = ipv6Check.matcher(ip).matches();
+ if (!ipv6Result) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/src/main/java/net/geedge/confagent/util/Tool.java b/src/main/java/net/geedge/confagent/util/Tool.java
index 250b0c2..a89f174 100644
--- a/src/main/java/net/geedge/confagent/util/Tool.java
+++ b/src/main/java/net/geedge/confagent/util/Tool.java
@@ -14,15 +14,12 @@ import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Type;
import java.math.BigDecimal;
-import java.net.URLDecoder;
+import java.net.*;
import java.nio.ByteBuffer;
import java.time.LocalDateTime;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAccessor;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Spliterator;
+import java.util.*;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
@@ -1103,4 +1100,50 @@ public class Tool {
}
}
+
+ public static class InetAddressUtil {
+ public static String getLocalHostLANAddress() throws UnknownHostException {
+ try {
+ List<InetAddress> inetAddressList = Tool.ListUtil.list(false);
+ // 遍历所有的网络接口
+ for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
+ NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
+ // 在所有的接口下再遍历IP
+ for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
+ InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
+ if (!inetAddr.isAnyLocalAddress() && !inetAddr.isLoopbackAddress() && !inetAddr.isLinkLocalAddress()) {
+ inetAddressList.add(inetAddr);
+ }
+ }
+ }
+
+ InetAddress inet6Address = inetAddressList.stream().filter(inetAddress -> inetAddress instanceof Inet6Address).findFirst().orElse(null);
+ if (Optional.ofNullable(inet6Address).isPresent()) {
+ String ipAddr = inet6Address.getHostAddress();
+ int index = ipAddr.indexOf('%');
+ if (index > 0) {
+ ipAddr = ipAddr.substring(0, index);
+ }
+ return ipAddr;
+ }
+
+ InetAddress inet4Address = inetAddressList.stream().findFirst().orElse(null);
+ if (Optional.ofNullable(inet4Address).isPresent()) {
+ return inet4Address.getHostAddress();
+ }
+
+ // 如果没有发现 non-loopback地址.只能用最次选的方案
+ InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
+ if (Optional.ofNullable(jdkSuppliedAddress).isPresent()) {
+ throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
+ }
+ return jdkSuppliedAddress.getHostAddress();
+ } catch (Exception e) {
+ UnknownHostException unknownHostException = new UnknownHostException(
+ "Failed to determine LAN address: " + e);
+ unknownHostException.initCause(e);
+ throw unknownHostException;
+ }
+ }
+ }
}