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

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

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

问题

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

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. )
  7. func main() {
  8. f, e := os.Open("/proc/meminfo")
  9. if e != nil {
  10. panic(e)
  11. }
  12. defer f.Close()
  13. s := bufio.NewScanner(f)
  14. for s.Scan() {
  15. var n int
  16. fmt.Sscanf(s.Text(), "MemFree: %d kB", &n)
  17. fmt.Println(n)
  18. }
  19. }

这给我提供了以下结果:

  1. 0
  2. 11260616
  3. 0
  4. 0
  5. 0
  6. 0
  7. 0
  8. 0
  9. 0
  10. 0
  11. 0
  12. 0
  13. 0
  14. 0
  15. 0
  16. 0
  17. 0
  18. 0
  19. 0
  20. 0
  21. 0
  22. 0
  23. 0
  24. 0
  25. 0
  26. 0
  27. 0
  28. 0
  29. 0
  30. 0
  31. 0
  32. 0
  33. 0
  34. 0
  35. 0
  36. 0
  37. 0
  38. 0
  39. 0
  40. 0
  41. 0
  42. 0
  43. 0
  44. 0
  45. 0
  46. 0
  47. 0
  48. 0
  49. 0
  50. 0
  51. 0
  52. 0
  53. 0
  54. 0

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

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

  1. MemTotal: 16314336 kB
  2. MemFree: 11268004 kB
  3. MemAvailable: 13955820 kB
  4. Buffers: 330284 kB
  5. Cached: 2536848 kB
  6. SwapCached: 0 kB
  7. Active: 1259348 kB
  8. Inactive: 3183140 kB
  9. Active(anon): 4272 kB
  10. Inactive(anon): 1578028 kB
  11. Active(file): 1255076 kB
  12. Inactive(file): 1605112 kB
  13. Unevictable: 0 kB
  14. Mlocked: 0 kB
  15. SwapTotal: 4194304 kB
  16. SwapFree: 4194304 kB
  17. Dirty: 96 kB
  18. Writeback: 0 kB
  19. AnonPages: 1411704 kB
  20. Mapped: 594408 kB
  21. Shmem: 6940 kB
  22. KReclaimable: 151936 kB
  23. Slab: 253384 kB
  24. SReclaimable: 151936 kB
  25. SUnreclaim: 101448 kB
  26. KernelStack: 17184 kB
  27. PageTables: 25060 kB
  28. NFS_Unstable: 0 kB
  29. Bounce: 0 kB
  30. WritebackTmp: 0 kB
  31. CommitLimit: 12351472 kB
  32. Committed_AS: 6092984 kB
  33. VmallocTotal: 34359738367 kB
  34. VmallocUsed: 40828 kB
  35. VmallocChunk: 0 kB
  36. Percpu: 5696 kB
  37. AnonHugePages: 720896 kB
  38. ShmemHugePages: 0 kB
  39. ShmemPmdMapped: 0 kB
  40. FileHugePages: 0 kB
  41. FilePmdMapped: 0 kB
  42. HugePages_Total: 0
  43. HugePages_Free: 0
  44. HugePages_Rsvd: 0
  45. HugePages_Surp: 0
  46. Hugepagesize: 2048 kB
  47. Hugetlb: 0 kB
  48. DirectMap4k: 230400 kB
  49. DirectMap2M: 11235328 kB
  50. 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:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "os"
  6. )
  7. func main() {
  8. f, e := os.Open("/proc/meminfo")
  9. if e != nil {
  10. panic(e)
  11. }
  12. defer f.Close()
  13. s := bufio.NewScanner(f)
  14. for s.Scan() {
  15. var n int
  16. fmt.Sscanf(s.Text(), "MemFree: %d kB", &n)
  17. fmt.Println(n)
  18. }
  19. }

Which gives me the following results:

  1. 0
  2. 11260616
  3. 0
  4. 0
  5. 0
  6. 0
  7. 0
  8. 0
  9. 0
  10. 0
  11. 0
  12. 0
  13. 0
  14. 0
  15. 0
  16. 0
  17. 0
  18. 0
  19. 0
  20. 0
  21. 0
  22. 0
  23. 0
  24. 0
  25. 0
  26. 0
  27. 0
  28. 0
  29. 0
  30. 0
  31. 0
  32. 0
  33. 0
  34. 0
  35. 0
  36. 0
  37. 0
  38. 0
  39. 0
  40. 0
  41. 0
  42. 0
  43. 0
  44. 0
  45. 0
  46. 0
  47. 0
  48. 0
  49. 0
  50. 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:

  1. MemTotal: 16314336 kB
  2. MemFree: 11268004 kB
  3. MemAvailable: 13955820 kB
  4. Buffers: 330284 kB
  5. Cached: 2536848 kB
  6. SwapCached: 0 kB
  7. Active: 1259348 kB
  8. Inactive: 3183140 kB
  9. Active(anon): 4272 kB
  10. Inactive(anon): 1578028 kB
  11. Active(file): 1255076 kB
  12. Inactive(file): 1605112 kB
  13. Unevictable: 0 kB
  14. Mlocked: 0 kB
  15. SwapTotal: 4194304 kB
  16. SwapFree: 4194304 kB
  17. Dirty: 96 kB
  18. Writeback: 0 kB
  19. AnonPages: 1411704 kB
  20. Mapped: 594408 kB
  21. Shmem: 6940 kB
  22. KReclaimable: 151936 kB
  23. Slab: 253384 kB
  24. SReclaimable: 151936 kB
  25. SUnreclaim: 101448 kB
  26. KernelStack: 17184 kB
  27. PageTables: 25060 kB
  28. NFS_Unstable: 0 kB
  29. Bounce: 0 kB
  30. WritebackTmp: 0 kB
  31. CommitLimit: 12351472 kB
  32. Committed_AS: 6092984 kB
  33. VmallocTotal: 34359738367 kB
  34. VmallocUsed: 40828 kB
  35. VmallocChunk: 0 kB
  36. Percpu: 5696 kB
  37. AnonHugePages: 720896 kB
  38. ShmemHugePages: 0 kB
  39. ShmemPmdMapped: 0 kB
  40. FileHugePages: 0 kB
  41. FilePmdMapped: 0 kB
  42. HugePages_Total: 0
  43. HugePages_Free: 0
  44. HugePages_Rsvd: 0
  45. HugePages_Surp: 0
  46. Hugepagesize: 2048 kB
  47. Hugetlb: 0 kB
  48. DirectMap4k: 230400 kB
  49. DirectMap2M: 11235328 kB
  50. 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:

确定