Files
kit.program/kit/src/glance/monitor.js
T
cheney 8ff4917d0c
TDevOpsCICD / build-kit (push) Successful in 6m11s
feat(kit): 实现 tcpc tcp 报文发收命令
- tcpc 支持 hex/文本发送、--headlen 大端长度头自动填充与收包校验、超时控制

refactor(killport): 支持 --dry 模式,Linux 下通过 docker-proxy 定位容器内真实进程(拆分至 linux/portpid.js)
2026-10-16 17:29:40 +08:00

80 lines
2.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 进程监控指标采集(仅支持 Linux)
* - CPU 占用率:两次采样 /proc/<pid>/stat 与 /proc/stat 差值计算,内部休眠约 1 秒
* - 内存占用:/proc/<pid>/status 的 VmRSS,单位 MB
* - 句柄数:/proc/<pid>/fd 目录条目数
* - 端口 -> pid:端口解析逻辑见 ../linux/portpid.js(含 docker 端口发布)
*/
const fs = require("fs");
const portpid = require("../linux/portpid");
const os = require("os");
function isLinux() {
return os.type() === "Linux";
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
function readPidTicks(pid) {
const txt = fs.readFileSync(`/proc/${pid}/stat`, "utf8");
// 字段 14=utime 15=stime,comm 可能含空格,按最后一个 ) 截断
const rest = txt.slice(txt.lastIndexOf(")") + 1).trim().split(/\s+/);
return Number(rest[11]) + Number(rest[12]);
}
function readCpuTotal() {
const line = fs.readFileSync("/proc/stat", "utf8").split("\n")[0];
// user nice system idle iowait irq softirq steal(guest 已计入 user)
const parts = line.trim().split(/\s+/).slice(1, 9).map(Number);
let total = 0;
for (const v of parts) {
total += Number.isFinite(v) ? v : 0;
}
return total;
}
function readMemMB(pid) {
const status = fs.readFileSync(`/proc/${pid}/status`, "utf8");
const m = status.match(/^VmRSS:\s+(\d+)\s+kB/m);
if (!m) {
return null;
}
return Math.round(Number(m[1]) / 1024 * 100) / 100;
}
function readHandleCount(pid) {
return fs.readdirSync(`/proc/${pid}/fd`, { withFileTypes: true }).length;
}
/**
* 采集单个进程的监控数据
* @param {number} pid
* @returns {Promise<{pid:number,cpu:number,mem:number,handle:number}|null>} 进程不存在/不可读返回 null
*/
async function collectPid(pid) {
try {
const beforePid = readPidTicks(pid);
const beforeTotal = readCpuTotal();
await sleep(1000);
const afterPid = readPidTicks(pid);
const afterTotal = readCpuTotal();
const totalDelta = afterTotal - beforeTotal;
const pidDelta = afterPid - beforePid;
const cpu = totalDelta > 0 ? Math.round(pidDelta / totalDelta * 10000) / 100 : 0;
const mem = readMemMB(pid);
const handle = readHandleCount(pid);
return { pid, cpu, mem, handle };
} catch (e) {
return null;
}
}
module.exports = {
isLinux,
collectPid,
findPortPid: portpid.findPortPid
};