主机内存总量改从 /proc/meminfo 读
os.totalmem() 底层是 sysinfo() 系统调用,LXC 里 lxcfs 只虚拟化 /proc 文件、拦不住系统调用,导致容器里显示的是宿主机的物理内存总量。 从 /proc/meminfo 读 MemTotal 才是容器限额,且与 MemAvailable 同源。
This commit is contained in:
+2
-1
@@ -12,6 +12,7 @@ import {
|
||||
cpuUsageBetween,
|
||||
parseGateway,
|
||||
parseMemAvailable,
|
||||
parseMemTotal,
|
||||
parseNameservers,
|
||||
} from '../shared/host-info.ts'
|
||||
import type { CpuTimes, ExitProbe, HostInfo } from '../shared/host-info.ts'
|
||||
@@ -56,7 +57,7 @@ export async function hostInfo(): Promise<HostInfo> {
|
||||
return {
|
||||
cpuUsage,
|
||||
cpuCount: os.cpus().length,
|
||||
memTotal: os.totalmem(),
|
||||
memTotal: parseMemTotal(meminfo) ?? os.totalmem(),
|
||||
memAvailable: parseMemAvailable(meminfo) ?? os.freemem(),
|
||||
// loadavg 在 Windows 上恒为 0,那不是「负载为零」而是「没有这个概念」
|
||||
load1: process.platform === 'win32' ? null : load,
|
||||
|
||||
@@ -3,9 +3,21 @@ import {
|
||||
cpuUsageBetween,
|
||||
parseGateway,
|
||||
parseMemAvailable,
|
||||
parseMemTotal,
|
||||
parseNameservers,
|
||||
} from './host-info.ts'
|
||||
|
||||
describe('parseMemTotal', () => {
|
||||
test('取 MemTotal 并换算成字节', () => {
|
||||
const meminfo = 'MemTotal: 2048000 kB\nMemFree: 100000 kB\nMemAvailable: 512000 kB\n'
|
||||
expect(parseMemTotal(meminfo)).toBe(2048000 * 1024)
|
||||
})
|
||||
|
||||
test('读不到 /proc/meminfo(非 Linux 平台)返回 null', () => {
|
||||
expect(parseMemTotal('')).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
describe('parseMemAvailable', () => {
|
||||
test('取 MemAvailable 并换算成字节', () => {
|
||||
const meminfo = 'MemTotal: 2048000 kB\nMemFree: 100000 kB\nMemAvailable: 512000 kB\n'
|
||||
|
||||
+19
-3
@@ -11,6 +11,7 @@ export interface HostInfo {
|
||||
/** 0-100。第一次请求没有参照快照,是 null */
|
||||
cpuUsage: number | null
|
||||
cpuCount: number
|
||||
/** 内存总量。Linux 用 MemTotal,其余平台退回 totalmem */
|
||||
memTotal: number
|
||||
/** 还能用的内存。Linux 用 MemAvailable,其余平台退回 freemem */
|
||||
memAvailable: number
|
||||
@@ -37,13 +38,28 @@ export interface ExitProbe {
|
||||
message?: string
|
||||
}
|
||||
|
||||
/** /proc/meminfo 里的 MemAvailable(内核估算的「还能用多少」),换算成字节。 */
|
||||
export function parseMemAvailable(meminfo: string): number | null {
|
||||
const match = /^MemAvailable:\s+(\d+)\s*kB/m.exec(meminfo)
|
||||
function meminfoBytes(meminfo: string, field: string): number | null {
|
||||
const match = new RegExp(`^${field}:\\s+(\\d+)\\s*kB`, 'm').exec(meminfo)
|
||||
if (!match) return null
|
||||
return Number(match[1]) * 1024
|
||||
}
|
||||
|
||||
/**
|
||||
* /proc/meminfo 里的 MemTotal,换算成字节。
|
||||
*
|
||||
* 不能用 os.totalmem():它底层是 sysinfo() 系统调用,LXC 里的 lxcfs 只虚拟化
|
||||
* /proc 下的文件、拦不住系统调用,所以 sysinfo() 返回的是宿主机的物理内存总量。
|
||||
* 从 /proc/meminfo 读才是容器视角,且与 MemAvailable 出自同一份数据。
|
||||
*/
|
||||
export function parseMemTotal(meminfo: string): number | null {
|
||||
return meminfoBytes(meminfo, 'MemTotal')
|
||||
}
|
||||
|
||||
/** /proc/meminfo 里的 MemAvailable(内核估算的「还能用多少」),换算成字节。 */
|
||||
export function parseMemAvailable(meminfo: string): number | null {
|
||||
return meminfoBytes(meminfo, 'MemAvailable')
|
||||
}
|
||||
|
||||
/**
|
||||
* /proc/net/route 里的默认网关。
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user