45 lines
1.4 KiB
TypeScript
45 lines
1.4 KiB
TypeScript
|
|
import type { Client } from 'ssh2'
|
||
|
|
import { execCommand, toFixedNum } from './common.js'
|
||
|
|
|
||
|
|
function parseDfLine(output: string): string[] | null {
|
||
|
|
const lines = output.split('\n').map((l) => l.trim()).filter(Boolean)
|
||
|
|
if (lines.length < 2) return null
|
||
|
|
return lines[1].split(/\s+/)
|
||
|
|
}
|
||
|
|
|
||
|
|
export async function collectDiskMetrics(
|
||
|
|
client: Client,
|
||
|
|
): Promise<{ percent: number | null; usedHuman: string | null; totalHuman: string | null; availableHuman: string | null }> {
|
||
|
|
let percent: number | null = null
|
||
|
|
let usedHuman: string | null = null
|
||
|
|
let totalHuman: string | null = null
|
||
|
|
let availableHuman: string | null = null
|
||
|
|
|
||
|
|
try {
|
||
|
|
const [human, bytes] = await Promise.all([
|
||
|
|
execCommand(client, "df -h -P / 2>/dev/null"),
|
||
|
|
execCommand(client, "df -B1 -P / 2>/dev/null"),
|
||
|
|
])
|
||
|
|
|
||
|
|
const humanParts = parseDfLine(human.stdout)
|
||
|
|
if (humanParts && humanParts.length >= 4) {
|
||
|
|
totalHuman = humanParts[1]
|
||
|
|
usedHuman = humanParts[2]
|
||
|
|
availableHuman = humanParts[3]
|
||
|
|
}
|
||
|
|
|
||
|
|
const byteParts = parseDfLine(bytes.stdout)
|
||
|
|
if (byteParts && byteParts.length >= 3) {
|
||
|
|
const total = Number(byteParts[1])
|
||
|
|
const used = Number(byteParts[2])
|
||
|
|
if (Number.isFinite(total) && total > 0 && Number.isFinite(used)) {
|
||
|
|
percent = toFixedNum((used / total) * 100)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} catch {
|
||
|
|
// best-effort
|
||
|
|
}
|
||
|
|
|
||
|
|
return { percent, usedHuman, totalHuman, availableHuman }
|
||
|
|
}
|