新增获取磁盘主机的信息

This commit is contained in:
2025-08-24 15:32:44 +08:00
parent ed21f9248e
commit c55d3f619a
17 changed files with 574 additions and 2 deletions

13
pom.xml
View File

@@ -43,6 +43,19 @@
<artifactId>commons-net</artifactId>
<version>3.11.0</version> <!-- 请根据需要使用最新版本 -->
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.14.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.18.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-08-24
*/
@RestController
@RequestMapping("/biz/diskMount")
public class DiskMountController {
}

View File

@@ -0,0 +1,18 @@
package com.mini.capi.biz.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 前端控制器
* </p>
*
* @author gaoxq
* @since 2025-08-24
*/
@RestController
@RequestMapping("/biz/sysHost")
public class SysHostController {
}

View File

@@ -0,0 +1,108 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
*
* </p>
*
* @author gaoxq
* @since 2025-08-24
*/
@Getter
@Setter
@TableName("biz_disk_mount")
public class DiskMount implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@TableField("create_time")
private LocalDateTime createTime;
@TableField("sys_host_id")
private String sysHostId;
/**
* 设备分区
*/
@TableField("disk_fs")
private String diskFs;
/**
* 总容量
*/
@TableField("size_kb")
private BigDecimal sizeKb;
/**
* 已用容量
*/
@TableField("used_kb")
private BigDecimal usedKb;
/**
* 可用容量
*/
@TableField("avail_kb")
private BigDecimal availKb;
/**
* 挂载路径
*/
@TableField("mount_point")
private String mountPoint;
@TableId(value = "disk_mount_id", type = IdType.AUTO)
private String diskMountId;
/**
* 租户id
*/
@TableField("f_tenant_id")
private String fTenantId;
/**
* 流程id
*/
@TableField("f_flow_id")
private String fFlowId;
/**
* 流程任务主键
*/
@TableField("f_flow_task_id")
private String fFlowTaskId;
/**
* 流程任务状态
*/
@TableField("f_flow_state")
private Integer fFlowState;
@Override
public String toString() {
return "DiskMount{" +
"sysHostId='" + sysHostId + '\'' +
", diskFs='" + diskFs + '\'' +
", sizeKb=" + sizeKb +
", usedKb=" + usedKb +
", availKb=" + availKb +
", mountPoint='" + mountPoint + '\'' +
'}';
}
}

View File

@@ -0,0 +1,107 @@
package com.mini.capi.biz.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
*
* </p>
*
* @author gaoxq
* @since 2025-08-24
*/
@Getter
@Setter
@TableName("biz_sys_host")
public class SysHost implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
@TableField("create_time")
private LocalDateTime createTime;
@TableId(value = "sys_host_id", type = IdType.AUTO)
private String sysHostId;
/**
* 人工/系统指定的主机唯一标识
*/
@TableField("host_tag")
private String hostTag;
@TableField("hostname")
private String hostname;
/**
* CPU架构
*/
@TableField("cpu_arch")
private String cpuArch;
/**
* CPU型号
*/
@TableField("cpu_model")
private String cpuModel;
/**
* CP 核心数
*/
@TableField("cpu_cores")
private Integer cpuCores;
/**
* CPU使用率
*/
@TableField("cpu_usage")
private String cpuUsage;
/**
* 租户id
*/
@TableField("f_tenant_id")
private String fTenantId;
/**
* 流程id
*/
@TableField("f_flow_id")
private String fFlowId;
/**
* 流程任务主键
*/
@TableField("f_flow_task_id")
private String fFlowTaskId;
/**
* 流程任务状态
*/
@TableField("f_flow_state")
private Integer fFlowState;
@Override
public String toString() {
return "SysHost{" +
"sysHostId='" + sysHostId + '\'' +
", hostTag='" + hostTag + '\'' +
", hostname='" + hostname + '\'' +
", cpuArch='" + cpuArch + '\'' +
", cpuModel='" + cpuModel + '\'' +
", cpuCores=" + cpuCores +
", cpuUsage='" + cpuUsage + '\'' +
'}';
}
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.DiskMount;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-08-24
*/
public interface DiskMountMapper extends BaseMapper<DiskMount> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.mapper;
import com.mini.capi.biz.domain.SysHost;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* Mapper 接口
* </p>
*
* @author gaoxq
* @since 2025-08-24
*/
public interface SysHostMapper extends BaseMapper<SysHost> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.DiskMount;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author gaoxq
* @since 2025-08-24
*/
public interface DiskMountService extends IService<DiskMount> {
}

View File

@@ -0,0 +1,16 @@
package com.mini.capi.biz.service;
import com.mini.capi.biz.domain.SysHost;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 服务类
* </p>
*
* @author gaoxq
* @since 2025-08-24
*/
public interface SysHostService extends IService<SysHost> {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.DiskMount;
import com.mini.capi.biz.mapper.DiskMountMapper;
import com.mini.capi.biz.service.DiskMountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-08-24
*/
@Service
public class DiskMountServiceImpl extends ServiceImpl<DiskMountMapper, DiskMount> implements DiskMountService {
}

View File

@@ -0,0 +1,20 @@
package com.mini.capi.biz.service.impl;
import com.mini.capi.biz.domain.SysHost;
import com.mini.capi.biz.mapper.SysHostMapper;
import com.mini.capi.biz.service.SysHostService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 服务实现类
* </p>
*
* @author gaoxq
* @since 2025-08-24
*/
@Service
public class SysHostServiceImpl extends ServiceImpl<SysHostMapper, SysHost> implements SysHostService {
}

View File

@@ -29,7 +29,7 @@ public class demo {
.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "/src/main/resources/mapper"));
})
.strategyConfig(builder -> {
builder.addInclude("biz_docker_host")
builder.addInclude("biz_sys_host,biz_disk_mount")
.addTablePrefix("biz_")
.entityBuilder()
.enableLombok()

View File

@@ -0,0 +1,126 @@
package com.mini.capi.utils;
import com.jcraft.jsch.*;
import com.mini.capi.biz.domain.DiskMount;
import com.mini.capi.biz.domain.SysHost;
import java.io.*;
import java.math.BigDecimal;
import java.util.*;
public final class HostInfo {
private static final String HOST_TAG = "c-api";
public static final class Result {
public final SysHost host;
public final List<DiskMount> disks;
Result(SysHost h, List<DiskMount> d) {
this.host = h;
this.disks = d;
}
}
/* ========== 主入口 ========== */
public static Result collect(String hostIp, int port, String username, String password) throws Exception {
Session session = null;
try {
session = createSession(hostIp, port, username, password);
SysHost host = collectHost(session);
List<DiskMount> disks = collectDisk(session);
disks.forEach(d -> d.setSysHostId(host.getSysHostId()));
return new Result(host, disks);
} finally {
if (session != null && session.isConnected()) {
session.disconnect();
}
}
}
/* ========== SSH 工具 ========== */
private static Session createSession(String ip, int port, String user, String pwd) throws JSchException {
JSch jsch = new JSch();
Session session = jsch.getSession(user, ip, port);
session.setPassword(pwd);
session.setConfig("StrictHostKeyChecking", "no");
session.connect(10_000);
return session;
}
private static String exec(Session session, String cmd) throws Exception {
ChannelExec ch = (ChannelExec) session.openChannel("exec");
ch.setCommand(cmd);
ByteArrayOutputStream out = new ByteArrayOutputStream();
ByteArrayOutputStream err = new ByteArrayOutputStream();
ch.setOutputStream(out);
ch.setErrStream(err);
ch.connect();
waitForExit(ch);
ch.disconnect();
String errStr = err.toString().trim();
if (!errStr.isEmpty()) {
throw new RuntimeException("Remote cmd error: " + errStr);
}
return out.toString().trim();
}
private static void waitForExit(ChannelExec ch) throws Exception {
long start = System.currentTimeMillis();
while (!ch.isClosed()) {
if (System.currentTimeMillis() - start > 30_000) {
throw new RuntimeException("Command timeout");
}
}
}
/* ========== 采集主机信息 ========== */
private static SysHost collectHost(Session session) throws Exception {
SysHost host = new SysHost();
String id = vId.getUid();
host.setSysHostId(id);
host.setHostTag(HOST_TAG);
host.setHostname(exec(session, "hostname -s"));
host.setCpuArch(exec(session, "uname -m"));
// CPU 型号:取 model name 第一行
String cpuInfo = exec(session, "cat /proc/cpuinfo | grep 'model name' | head -1");
host.setCpuModel(cpuInfo.contains(":") ? cpuInfo.split(":", 2)[1].trim() : null);
// 核心数
String cores = exec(session, "nproc --all");
host.setCpuCores(parseInt(cores));
// CPU 使用率top -bn1 取 idle 字段
String top = exec(session, "top -bn1 | grep 'Cpu(s)'");
host.setCpuUsage(top);
return host;
}
/* ========== 采集磁盘信息 ========== */
private static List<DiskMount> collectDisk(Session session) throws Exception {
String df = exec(session, "df -k -P | tail -n +2"); // 去掉标题行
List<DiskMount> list = new ArrayList<>();
for (String line : df.split("\n")) {
String[] arr = line.trim().split("\\s+");
if (arr.length < 6) continue; // 跳过异常行
DiskMount d = new DiskMount();
d.setDiskFs(arr[0]);
d.setSizeKb(new BigDecimal(arr[1]));
d.setUsedKb(new BigDecimal(arr[2]));
d.setAvailKb(new BigDecimal(arr[3]));
d.setMountPoint(arr[5]);
list.add(d);
}
return list;
}
/* ========== 工具方法 ========== */
private static Integer parseInt(String s) {
try {
return Integer.parseInt(s.trim());
} catch (Exception e) {
return null;
}
}
}

View File

@@ -54,7 +54,6 @@ public class docker {
ChannelExec channel = (ChannelExec) session.openChannel("exec");
channel.setCommand(command);
channel.setInputStream(null);
InputStream in = channel.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));

View File

@@ -0,0 +1,27 @@
package com.mini.capi.utils;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class vId {
private static final SecureRandom RAND = new SecureRandom();
private static final DateTimeFormatter DF = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");
private vId() {}
/**
*
* 时间戳唯一编号
*/
public static String getUid() {
// 17 位时间
String tm = LocalDateTime.now().format(DF);
// 25 位随机数字(高位补零)
long rand = Math.abs(RAND.nextLong()) % (long) Math.pow(10, 15);
return tm + String.format("%015d", rand);
}
}

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mini.capi.biz.mapper.DiskMountMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.mini.capi.biz.domain.DiskMount">
<id column="disk_mount_id" property="diskMountId" />
<result column="create_time" property="createTime" />
<result column="sys_host_id" property="sysHostId" />
<result column="disk_fs" property="diskFs" />
<result column="size_kb" property="sizeKb" />
<result column="used_kb" property="usedKb" />
<result column="avail_kb" property="availKb" />
<result column="mount_point" property="mountPoint" />
<result column="f_tenant_id" property="fTenantId" />
<result column="f_flow_id" property="fFlowId" />
<result column="f_flow_task_id" property="fFlowTaskId" />
<result column="f_flow_state" property="fFlowState" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
create_time, sys_host_id, disk_fs, size_kb, used_kb, avail_kb, mount_point, disk_mount_id, f_tenant_id, f_flow_id, f_flow_task_id, f_flow_state
</sql>
</mapper>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.mini.capi.biz.mapper.SysHostMapper">
<!-- 通用查询映射结果 -->
<resultMap id="BaseResultMap" type="com.mini.capi.biz.domain.SysHost">
<id column="sys_host_id" property="sysHostId" />
<result column="create_time" property="createTime" />
<result column="host_tag" property="hostTag" />
<result column="hostname" property="hostname" />
<result column="cpu_arch" property="cpuArch" />
<result column="cpu_model" property="cpuModel" />
<result column="cpu_cores" property="cpuCores" />
<result column="cpu_usage" property="cpuUsage" />
<result column="f_tenant_id" property="fTenantId" />
<result column="f_flow_id" property="fFlowId" />
<result column="f_flow_task_id" property="fFlowTaskId" />
<result column="f_flow_state" property="fFlowState" />
</resultMap>
<!-- 通用查询结果列 -->
<sql id="Base_Column_List">
create_time, sys_host_id, host_tag, hostname, cpu_arch, cpu_model, cpu_cores, cpu_usage, f_tenant_id, f_flow_id, f_flow_task_id, f_flow_state
</sql>
</mapper>