Extracting memory and swap info from /proc/meminfo in Golang

huangapple go评论73阅读模式
英文:

Extracting memory and swap info from /proc/meminfo in Golang

问题

我想从Golang中的/proc/meminfo文件中提取MemTotal、MemFree、MemAvailable、SwapTotal和SwapFree的值。到目前为止,我最接近的方法是使用fmt.Sscanf(),它可以一次给我一个想要的值,但我也得到了许多输出为零的行。以下是我使用的代码:

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	f, e := os.Open("/proc/meminfo")
	if e != nil {
		panic(e)
	}
	defer f.Close()
	s := bufio.NewScanner(f)
	for s.Scan() {
		var n int
		fmt.Sscanf(s.Text(), "MemFree: %d kB", &n)
		fmt.Println(n)
	}
}

这给我提供了以下结果:

0
11260616
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

所以,第一个问题是,有没有办法将结果限制为我想要的一个值(非零)?或者,有没有更好的方法来处理这个问题?

我的/proc/meminfo文件如下所示:

MemTotal:       16314336 kB
MemFree:        11268004 kB
MemAvailable:   13955820 kB
Buffers:          330284 kB
Cached:          2536848 kB
SwapCached:            0 kB
Active:          1259348 kB
Inactive:        3183140 kB
Active(anon):       4272 kB
Inactive(anon):  1578028 kB
Active(file):    1255076 kB
Inactive(file):  1605112 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       4194304 kB
SwapFree:        4194304 kB
Dirty:                96 kB
Writeback:             0 kB
AnonPages:       1411704 kB
Mapped:           594408 kB
Shmem:              6940 kB
KReclaimable:     151936 kB
Slab:             253384 kB
SReclaimable:     151936 kB
SUnreclaim:       101448 kB
KernelStack:       17184 kB
PageTables:        25060 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    12351472 kB
Committed_AS:    6092984 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       40828 kB
VmallocChunk:          0 kB
Percpu:             5696 kB
AnonHugePages:    720896 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
FileHugePages:         0 kB
FilePmdMapped:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB
DirectMap4k:      230400 kB
DirectMap2M:    11235328 kB
DirectMap1G:    14680064 kB

请问,有没有办法将结果限制为我想要的一个值(非零)?或者,有没有更好的方法来处理这个问题?

英文:

I'd like to extract the values for MemTotal, MemFree, MemAvailable, SwapTotal and SwapFree from /proc/meminfo in Golang. The closest I've gotten so far, is to use fmt.Sscanf() which will give me the values I want one at a time, but I'm also getting many lines with zeros for output. Here's the code I'm using:

package main

import (
	"bufio"
	"fmt"
	"os"
)

func main() {
	f, e := os.Open("/proc/meminfo")
	if e != nil {
		panic(e)
	}
	defer f.Close()
	s := bufio.NewScanner(f)
	for s.Scan() {
		var n int
		fmt.Sscanf(s.Text(), "MemFree: %d kB", &n)
		fmt.Println(n)
	}
}

Which gives me the following results:

0
11260616
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0

So the first question, is there a way to limit the results to the one value (non-zero) I'm after? Or, is there a better way to approach this altogether?

My /proc/meminfo file looks like this:

MemTotal:       16314336 kB
MemFree:        11268004 kB
MemAvailable:   13955820 kB
Buffers:          330284 kB
Cached:          2536848 kB
SwapCached:            0 kB
Active:          1259348 kB
Inactive:        3183140 kB
Active(anon):       4272 kB
Inactive(anon):  1578028 kB
Active(file):    1255076 kB
Inactive(file):  1605112 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       4194304 kB
SwapFree:        4194304 kB
Dirty:                96 kB
Writeback:             0 kB
AnonPages:       1411704 kB
Mapped:           594408 kB
Shmem:              6940 kB
KReclaimable:     151936 kB
Slab:             253384 kB
SReclaimable:     151936 kB
SUnreclaim:       101448 kB
KernelStack:       17184 kB
PageTables:        25060 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    12351472 kB
Committed_AS:    6092984 kB
VmallocTotal:   34359738367 kB
VmallocUsed:       40828 kB
VmallocChunk:          0 kB
Percpu:             5696 kB
AnonHugePages:    720896 kB
ShmemHugePages:        0 kB
ShmemPmdMapped:        0 kB
FileHugePages:         0 kB
FilePmdMapped:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
Hugetlb:               0 kB
DirectMap4k:      230400 kB
DirectMap2M:    11235328 kB
DirectMap1G:    14680064 kB

答案1

得分: 1

注意,s.Scan()逐行读取输入。如果一行不符合fmt.Sscanf给定的格式字符串,你的程序会将var n int声明在循环内部,输出0。我的建议是检查fmt.Sscanf返回的第一个结果,即匹配的项数。所以,如果第一个结果是1,说明有匹配,你可以输出该值。在这里可以看到一个工作示例:https://go.dev/play/p/RtBKusGg8wV

编辑:我尽量保持与你的代码尽可能接近。可能还会有其他问题,因为使用的测量单位可能会根据man页面而有所不同。然而,如果你的系统中涉及的值总是以"kB"输出,这可能已经足够满足你的需求。

英文:

Note, s.Scan() reads the input line by line. If a line does not match the format string given to fmt.Sscanf, your program outputs 0 as var n int is declared inside the loop. My suggestion is to check the first result returned by fmt.Sscanf`, i.e., the number of items matched. So, if first result is 1 you have a match and you can output the value. See working example here: https://go.dev/play/p/RtBKusGg8wV

EDIT: I tried to stay as close as possible to your code. There may be further issues as the unit of measurement used may vary according to the man pages. It may be good enough for your use case, however, if the the values in question on your systems are always output in "kB".

答案2

得分: 0

我想从Golang中的/proc/meminfo文件中提取MemTotal、MemFree、MemAvailable、SwapTotal和SwapFree的值。

当我看到你提供的/proc/meminfo文件中的值时,我想到了一个映射:使用第一列的项作为键,第二列的项作为值的键值对。

为了简单起见,你可以最初使用map[string]string来收集数据,然后在需要时将其转换为特定的类型。

然后,你可以使用"comma ok"惯用法来检查是否有可用于检索特定数据的值。

如果你不关心具体的值,只想要非零值,你可以在将它们放入映射之前过滤键值对:确保它们不为零。我建议在进行任何比较之前明确地去除空格。

编辑:注意,我在使用其他方法时遇到了问题,最终切换到使用bufio.Scanner来处理我正在使用的文件(也在/proc文件系统中)。

英文:

> I'd like to extract the values for MemTotal, MemFree, MemAvailable, SwapTotal and SwapFree from /proc/meminfo in Golang.

When I look at the values you provided from /proc/meminfo I think of a map: key/value pairs using items from the first column as keys and items from the second column as values.

To keep it simple, you could use map[string]string initially to collect, then convert where needed later to a specific type.

From there, you could use the comma ok idiom to check whether values are available for the specific data you'd like to retrieve.

If you didn't care about the specific values, you just wanted anything that was non-zero you could filter key/value pairs before you put them in the map: assert that they're not zero. I'd recommend explicitly trim spaces before any comparisons that you may make.

EDIT: Note, I ran into issues using other approaches and eventually switched to using a bufio.Scanner to process the file I was working with (also in the /proc filesystem).

huangapple
  • 本文由 发表于 2022年12月16日 04:54:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/74817453.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定