v1.1初始化
This commit is contained in:
@@ -1,15 +1,17 @@
|
||||
package com.tongran.agent.client.utils;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.tongran.agent.client.core.vo.NetworkInterfaceInfo;
|
||||
import org.snmp4j.smi.OID;
|
||||
import oshi.hardware.NetworkIF;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.net.UnknownHostException;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
@@ -240,4 +242,314 @@ public class AgentUtil {
|
||||
return swapped;
|
||||
}
|
||||
|
||||
/**
|
||||
* 收集所有 Ethernet 类型网卡信息
|
||||
*/
|
||||
public static List<NetworkInterfaceInfo> collectNetworkInfo() throws Exception {
|
||||
List<NetworkInterfaceInfo> result = new ArrayList<>();
|
||||
// String publicIp = getPublicIp(); // 获取公网 IP(全局出口)
|
||||
String ipInfo = PublicIpFetcher.getPublicIp();
|
||||
// System.out.println("完整信息: " + ipInfo);
|
||||
String publicIp = PublicIpFetcher.extractIp(ipInfo);
|
||||
if (publicIp != null) {
|
||||
System.out.println("公网 IP: " + publicIp);
|
||||
} else {
|
||||
System.out.println("未能提取 IP 地址");
|
||||
}
|
||||
|
||||
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
|
||||
|
||||
while (interfaces.hasMoreElements()) {
|
||||
NetworkInterface ni = interfaces.nextElement();
|
||||
|
||||
// 跳过回环、虚拟、关闭的接口
|
||||
if (ni.isLoopback() || ni.isVirtual() || !ni.isUp()) continue;
|
||||
|
||||
// 判断是否为 Ethernet(通过名称约定:eth*, en*, 等)
|
||||
String name = ni.getName();
|
||||
if (!isEthernetInterface(name)) continue;
|
||||
|
||||
NetworkInterfaceInfo info = NetworkInterfaceInfo.builder()
|
||||
.name(name)
|
||||
.mac(getMacAddress(ni))
|
||||
.ipv4(getIPv4Address(ni))
|
||||
.gateway(getGatewayAddress()) // 网关通常是默认路由,全局一致
|
||||
.publicIp(publicIp)
|
||||
.build();
|
||||
|
||||
// 如果有公网 IP,查询归属地
|
||||
if (publicIp != null && !publicIp.isEmpty()) {
|
||||
JSONObject location = queryIpLocation(publicIp);
|
||||
if (location != null) {
|
||||
info.setCarrier(location.getStr("org", "未知").replaceAll("^AS\\d+\\s*", ""));
|
||||
info.setProvince(location.getStr("region", "未知"));
|
||||
info.setCity(location.getStr("city", "未知"));
|
||||
} else {
|
||||
info.setCarrier("查询失败");
|
||||
info.setProvince("查询失败");
|
||||
info.setCity("查询失败");
|
||||
}
|
||||
}
|
||||
|
||||
result.add(info);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否为 Ethernet 类型网卡(基于常见命名)
|
||||
*/
|
||||
private static boolean isEthernetInterface(String name) {
|
||||
return name.startsWith("eth") || // Linux 传统
|
||||
name.startsWith("en") || // systemd 命名 (enp3s0)
|
||||
name.startsWith("em"); // 有些主板网卡
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 MAC 地址
|
||||
*/
|
||||
private static String getMacAddress(NetworkInterface ni) {
|
||||
try {
|
||||
byte[] mac = ni.getHardwareAddress();
|
||||
if (mac == null) return "N/A";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < mac.length; i++) {
|
||||
sb.append(String.format("%02X", mac[i]));
|
||||
if (i < mac.length - 1) sb.append(":");
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取第一个 IPv4 地址
|
||||
*/
|
||||
private static String getIPv4Address(NetworkInterface ni) {
|
||||
Enumeration<InetAddress> addresses = ni.getInetAddresses();
|
||||
while (addresses.hasMoreElements()) {
|
||||
InetAddress addr = addresses.nextElement();
|
||||
if (addr instanceof Inet4Address) {
|
||||
return addr.getHostAddress();
|
||||
}
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取默认网关(调用 shell 命令)
|
||||
*/
|
||||
private static String getGatewayAddress() {
|
||||
try {
|
||||
Process process = Runtime.getRuntime().exec("ip route");
|
||||
java.util.Scanner scanner = new java.util.Scanner(process.getInputStream());
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
if (line.startsWith("default")) {
|
||||
String[] parts = line.split(" ");
|
||||
return parts[2]; // default via <gateway> dev ...
|
||||
}
|
||||
}
|
||||
scanner.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公网 IP
|
||||
*/
|
||||
private static String getPublicIp() {
|
||||
return sendHttpGet("https://ifconfig.me");
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询 IP 归属地(使用 ipinfo.io)
|
||||
*/
|
||||
private static JSONObject queryIpLocation(String ip) {
|
||||
String url = "https://ipinfo.io/" + ip + "/json";
|
||||
String response = sendHttpGet(url);
|
||||
AssertLog.info("查询 IP 归属地={}", response);
|
||||
if (response != null) {
|
||||
try {
|
||||
return new JSONObject(response);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送 HTTP GET 请求
|
||||
*/
|
||||
private static String sendHttpGet(String urlString) {
|
||||
try {
|
||||
URL url = new URL(urlString);
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("GET");
|
||||
conn.setConnectTimeout(5000);
|
||||
conn.setReadTimeout(5000);
|
||||
|
||||
if (conn.getResponseCode() == 200) {
|
||||
java.util.Scanner scanner = new java.util.Scanner(conn.getInputStream());
|
||||
String result = scanner.useDelimiter("\\A").next();
|
||||
scanner.close();
|
||||
return result;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("HTTP 请求失败: " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void bufferedWriter(String filePath, String[] lines){
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(
|
||||
Paths.get(filePath),
|
||||
StandardCharsets.UTF_8,
|
||||
StandardOpenOption.CREATE, // 创建文件
|
||||
StandardOpenOption.TRUNCATE_EXISTING // 覆盖写入
|
||||
)) {
|
||||
for (String line : lines) {
|
||||
writer.write(line);
|
||||
writer.newLine(); // 换行
|
||||
}
|
||||
System.out.println("文件写入完成!");
|
||||
} catch (IOException e) {
|
||||
System.err.println("写入异常:" + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 /etc/issue 文件的第二行内容
|
||||
* @return 第二行字符串,如果不存在则返回 null
|
||||
*/
|
||||
public static String getDeviceSN() {
|
||||
Path issuePath = Paths.get("/etc/issue");
|
||||
if (!Files.exists(issuePath)) {
|
||||
System.err.println("文件不存在: /etc/issue");
|
||||
return null;
|
||||
}
|
||||
if (!Files.isReadable(issuePath)) {
|
||||
System.err.println("无读取权限: /etc/issue");
|
||||
return null;
|
||||
}
|
||||
try (BufferedReader reader = Files.newBufferedReader(issuePath)) {
|
||||
String line;
|
||||
int lineNumber = 0;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
line = line.trim();
|
||||
if (!line.isEmpty()) { // 只计数非空行
|
||||
lineNumber++;
|
||||
if (lineNumber == 2) {
|
||||
return line;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 如果文件少于两行
|
||||
System.err.println("文件行数不足,只有 " + lineNumber + " 行");
|
||||
return null;
|
||||
} catch (NoSuchFileException e) {
|
||||
System.err.println("文件未找到: " + e.getMessage());
|
||||
return null;
|
||||
} catch (IOException e) {
|
||||
System.err.println("读取文件异常: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
List<NetworkInterfaceInfo> infos = collectNetworkInfo();
|
||||
for (NetworkInterfaceInfo info : infos) {
|
||||
System.out.println(info);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getFileMD5(String filePath) {
|
||||
// 检查文件是否存在
|
||||
Path path = Paths.get(filePath);
|
||||
if (!Files.exists(path)) {
|
||||
System.out.println("文件不存在: " + filePath);
|
||||
return null;
|
||||
}
|
||||
// 检查是否是文件(不是目录)
|
||||
if (!Files.isRegularFile(path)) {
|
||||
System.out.println("路径不是文件: " + filePath);
|
||||
return null;
|
||||
}
|
||||
// 检查文件是否可读
|
||||
if (!Files.isReadable(path)) {
|
||||
System.out.println("文件不可读: " + filePath);
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||
try (FileInputStream fis = new FileInputStream(filePath)) {
|
||||
byte[] buffer = new byte[4096];
|
||||
int length;
|
||||
while ((length = fis.read(buffer)) != -1) {
|
||||
md.update(buffer, 0, length);
|
||||
}
|
||||
}
|
||||
byte[] digest = md.digest();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : digest) {
|
||||
sb.append(String.format("%02x", b));
|
||||
}
|
||||
return sb.toString();
|
||||
} catch (NoSuchAlgorithmException | IOException e) {
|
||||
System.out.println("计算MD5失败: " + e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 安排脚本在 3 分钟后执行
|
||||
*/
|
||||
public static void scheduleScriptIn3Minutes(String SCRIPT_PATH) {
|
||||
// 使用 at 命令:3 minutes from now
|
||||
String atCommand = String.format("echo '%s' | at now + 3 minutes", SCRIPT_PATH);
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder("bash", "-c", atCommand);
|
||||
pb.redirectErrorStream(true); // 合并 stdout 和 stderr
|
||||
|
||||
try {
|
||||
Process process = pb.start();
|
||||
|
||||
// 读取命令输出(at 通常会打印任务编号)
|
||||
java.io.BufferedReader reader = new java.io.BufferedReader(
|
||||
new java.io.InputStreamReader(process.getInputStream())
|
||||
);
|
||||
|
||||
String line;
|
||||
StringBuilder output = new StringBuilder();
|
||||
while ((line = reader.readLine()) != null) {
|
||||
output.append(line).append("\n");
|
||||
}
|
||||
reader.close();
|
||||
|
||||
int exitCode = process.waitFor();
|
||||
if (exitCode == 0) {
|
||||
System.out.println("✅ 成功安排脚本在 3 分钟后执行:");
|
||||
System.out.println(" 脚本: " + SCRIPT_PATH);
|
||||
if (output.length() > 0) {
|
||||
System.out.println(" at 响应: " + output.toString().trim());
|
||||
}
|
||||
} else {
|
||||
System.err.println("❌ 调度失败,exit code: " + exitCode);
|
||||
System.err.println(" 输出: " + output.toString().trim());
|
||||
}
|
||||
|
||||
} catch (IOException | InterruptedException e) {
|
||||
System.err.println("执行 at 命令时出错: " + e.getMessage());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user