update
This commit is contained in:
55
ts/smartmetrics.pidtree.ts
Normal file
55
ts/smartmetrics.pidtree.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import * as fs from 'fs';
|
||||
|
||||
// Get all descendant PIDs of the given root PID by reading /proc/<pid>/stat.
|
||||
// Returns an array of descendant PIDs (excludes the root itself).
|
||||
export async function getChildPids(rootPid: number): Promise<number[]> {
|
||||
const parentMap = new Map<number, number[]>(); // parent → children
|
||||
|
||||
let entries: string[];
|
||||
try {
|
||||
entries = fs.readdirSync('/proc');
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
|
||||
for (const entry of entries) {
|
||||
const pid = parseInt(entry, 10);
|
||||
if (isNaN(pid)) continue;
|
||||
|
||||
try {
|
||||
const stat = fs.readFileSync(`/proc/${pid}/stat`, 'utf8');
|
||||
// Format: pid (comm) state ppid ...
|
||||
// comm can contain spaces and parentheses, so find the last ')' first
|
||||
const closeParenIdx = stat.lastIndexOf(')');
|
||||
if (closeParenIdx === -1) continue;
|
||||
const afterComm = stat.slice(closeParenIdx + 2); // skip ') '
|
||||
const fields = afterComm.split(' ');
|
||||
const ppid = parseInt(fields[1], 10); // field index 1 after state is ppid
|
||||
|
||||
if (!parentMap.has(ppid)) {
|
||||
parentMap.set(ppid, []);
|
||||
}
|
||||
parentMap.get(ppid)!.push(pid);
|
||||
} catch {
|
||||
// Process may have exited between readdir and readFile
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// BFS from rootPid to collect all descendants
|
||||
const result: number[] = [];
|
||||
const queue: number[] = [rootPid];
|
||||
|
||||
while (queue.length > 0) {
|
||||
const current = queue.shift()!;
|
||||
const children = parentMap.get(current);
|
||||
if (children) {
|
||||
for (const child of children) {
|
||||
result.push(child);
|
||||
queue.push(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user