meminfo_linux.go 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package meminfo
  2. import (
  3. "bufio"
  4. "io"
  5. "os"
  6. "strconv"
  7. "strings"
  8. )
  9. // readMemInfo retrieves memory statistics of the host system and returns a
  10. // Memory type.
  11. func readMemInfo() (*Memory, error) {
  12. file, err := os.Open("/proc/meminfo")
  13. if err != nil {
  14. return nil, err
  15. }
  16. defer file.Close()
  17. return parseMemInfo(file)
  18. }
  19. // parseMemInfo parses the /proc/meminfo file into
  20. // a Memory object given an io.Reader to the file.
  21. // Throws error if there are problems reading from the file
  22. func parseMemInfo(reader io.Reader) (*Memory, error) {
  23. meminfo := &Memory{}
  24. scanner := bufio.NewScanner(reader)
  25. memAvailable := int64(-1)
  26. for scanner.Scan() {
  27. // Expected format: ["MemTotal:", "1234", "kB"]
  28. parts := strings.Fields(scanner.Text())
  29. // Sanity checks: Skip malformed entries.
  30. if len(parts) < 3 || parts[2] != "kB" {
  31. continue
  32. }
  33. // Convert to bytes.
  34. size, err := strconv.Atoi(parts[1])
  35. if err != nil {
  36. continue
  37. }
  38. // Convert to KiB
  39. bytes := int64(size) * 1024
  40. switch parts[0] {
  41. case "MemTotal:":
  42. meminfo.MemTotal = bytes
  43. case "MemFree:":
  44. meminfo.MemFree = bytes
  45. case "MemAvailable:":
  46. memAvailable = bytes
  47. case "SwapTotal:":
  48. meminfo.SwapTotal = bytes
  49. case "SwapFree:":
  50. meminfo.SwapFree = bytes
  51. }
  52. }
  53. if memAvailable != -1 {
  54. meminfo.MemFree = memAvailable
  55. }
  56. // Handle errors that may have occurred during the reading of the file.
  57. if err := scanner.Err(); err != nil {
  58. return nil, err
  59. }
  60. return meminfo, nil
  61. }