Golang : Get hardware information such as disk, memory and CPU usage




For this tutorial, we will learn how to extract hardware level information with Golang. Accessing hardware level information such as CPU usage percentage and disk partition information can be useful in a situation such as when you need to query the hardware ID or serial numbers without physically opening up the casing or you need to use the hardware information for tracking and troubleshooting purposes.

For my own personal use, I need it to query couples of raspberry-Pi computers, Linux desktops and a Mac.

In this code example below, we will use the cross-platform github.com/shirou/gopsutil package to find out the CPU utilization level and other system process statuses via Golang. The queried information will be exposed via web interface.

Before you start, please

$>go get github.com/shirou/gopsutil/...

Here you go!


 package main

 import (
 "fmt"
 "github.com/shirou/gopsutil/cpu"
 "github.com/shirou/gopsutil/disk"
 "github.com/shirou/gopsutil/host"
 "github.com/shirou/gopsutil/mem"
 "github.com/shirou/gopsutil/net"
 "net/http"
 "runtime"
 "strconv"
 )

 func dealwithErr(err error) {
 if err != nil {
 fmt.Println(err)
 //os.Exit(-1)
 }
 }

 func GetHardwareData(w http.ResponseWriter, r *http.Request) {
 runtimeOS := runtime.GOOS
 // memory
 vmStat, err := mem.VirtualMemory()
 dealwithErr(err)

 // disk - start from "/" mount point for Linux
 // might have to change for Windows!!
 // don't have a Window to test this out, if detect OS == windows
 // then use "\" instead of "/"

 diskStat, err := disk.Usage("/")
 dealwithErr(err)

 // cpu - get CPU number of cores and speed
 cpuStat, err := cpu.Info()
 dealwithErr(err)
 percentage, err := cpu.Percent(0, true)
 dealwithErr(err)

 // host or machine kernel, uptime, platform Info
 hostStat, err := host.Info()
 dealwithErr(err)

 // get interfaces MAC/hardware address
 interfStat, err := net.Interfaces()
 dealwithErr(err)

 html := "<html>OS : " + runtimeOS + "<br>"
 html = html + "Total memory: " + strconv.FormatUint(vmStat.Total, 10) + " bytes <br>"
 html = html + "Free memory: " + strconv.FormatUint(vmStat.Free, 10) + " bytes<br>"
 html = html + "Percentage used memory: " + strconv.FormatFloat(vmStat.UsedPercent, 'f', 2, 64) + "%<br>"

 // get disk serial number.... strange... not available from disk package at compile time
 // undefined: disk.GetDiskSerialNumber
 //serial := disk.GetDiskSerialNumber("/dev/sda")

 //html = html + "Disk serial number: " + serial + "<br>"

 html = html + "Total disk space: " + strconv.FormatUint(diskStat.Total, 10) + " bytes <br>"
 html = html + "Used disk space: " + strconv.FormatUint(diskStat.Used, 10) + " bytes<br>"
 html = html + "Free disk space: " + strconv.FormatUint(diskStat.Free, 10) + " bytes<br>"
 html = html + "Percentage disk space usage: " + strconv.FormatFloat(diskStat.UsedPercent, 'f', 2, 64) + "%<br>"

 // since my machine has one CPU, I'll use the 0 index
 // if your machine has more than 1 CPU, use the correct index
 // to get the proper data
 html = html + "CPU index number: " + strconv.FormatInt(int64(cpuStat[0].CPU), 10) + "<br>"
 html = html + "VendorID: " + cpuStat[0].VendorID + "<br>"
 html = html + "Family: " + cpuStat[0].Family + "<br>"
 html = html + "Number of cores: " + strconv.FormatInt(int64(cpuStat[0].Cores), 10) + "<br>"
 html = html + "Model Name: " + cpuStat[0].ModelName + "<br>"
 html = html + "Speed: " + strconv.FormatFloat(cpuStat[0].Mhz, 'f', 2, 64) + " MHz <br>"

 for idx, cpupercent := range percentage {
 html = html + "Current CPU utilization: [" + strconv.Itoa(idx) + "] " + strconv.FormatFloat(cpupercent, 'f', 2, 64) + "%<br>"
 }

 html = html + "Hostname: " + hostStat.Hostname + "<br>"
 html = html + "Uptime: " + strconv.FormatUint(hostStat.Uptime, 10) + "<br>"
 html = html + "Number of processes running: " + strconv.FormatUint(hostStat.Procs, 10) + "<br>"

 // another way to get the operating system name
 // both darwin for Mac OSX, For Linux, can be ubuntu as platform
 // and linux for OS

 html = html + "OS: " + hostStat.OS + "<br>"
 html = html + "Platform: " + hostStat.Platform + "<br>"

 // the unique hardware id for this machine
 html = html + "Host ID(uuid): " + hostStat.HostID + "<br>"

 for _, interf := range interfStat {
 html = html + "------------------------------------------------------<br>"
 html = html + "Interface Name: " + interf.Name + "<br>"

 if interf.HardwareAddr != "" {
 html = html + "Hardware(MAC) Address: " + interf.HardwareAddr + "<br>"
 }

 for _, flag := range interf.Flags {
 html = html + "Interface behavior or flags: " + flag + "<br>"
 }

 for _, addr := range interf.Addrs {
 html = html + "IPv6 or IPv4 addresses: " + addr.String() + "<br>"

 }

 }

 html = html + "</html>"

 w.Write([]byte(html))

 }

 func SayName(w http.ResponseWriter, r *http.Request) {
 w.Write([]byte("Hello, I'm a machine and my name is [whatever]"))
 }

 func main() {
 mux := http.NewServeMux()

 mux.HandleFunc("/", SayName)
 mux.HandleFunc("/gethwdata", GetHardwareData)

 http.ListenAndServe(":8080", mux)

 }

Sample output(point browser to http://localhost:8080/gethwdata) :

OS : darwin

Total memory: 4294967296 bytes

Free memory: 24223744 bytes

Percentage used memory: 76.96%

Total disk space: 119174365184 bytes

Used disk space: 109002297344 bytes

Free disk space: 9909923840 bytes

Percentage disk space usage: 91.46%

CPU index number: 0

VendorID: GenuineIntel

Family: 6

Number of cores: 2

Model Name: Intel(R) Core(TM) i3-3220 CPU @ 3.30GHz

Speed: 3292.00 MHz

Current CPU utilization: [0] 55.49%

Current CPU utilization: 1 27.71%

Current CPU utilization: 2 55.33%

Current CPU utilization: 3 26.79%

Hostname: Sweets-Mac-Pro.local

Uptime: 9045

Number of processes running: 211

OS: darwin

Platform: darwin

Host ID(uuid): FE3619E6-270B-34A6-BBD7-BED74EC32693

------------------------------------------------------

Interface Name: lo0

Interface behavior or flags: up

Interface behavior or flags: loopback

Interface behavior or flags: multicast

IPv6 or IPv4 addresses: {"addr":"::1/128"}

IPv6 or IPv4 addresses: {"addr":"127.0.0.1/8"}

IPv6 or IPv4 addresses: {"addr":"fe80::1/64"}

------------------------------------------------------

Interface Name: gif0

Interface behavior or flags: pointtopoint

Interface behavior or flags: multicast

------------------------------------------------------

Interface Name: stf0

------------------------------------------------------

Interface Name: en3

Hardware(MAC) Address: 18:a6:f7:16:e8:0b

Interface behavior or flags: up

Interface behavior or flags: broadcast

Interface behavior or flags: multicast

IPv6 or IPv4 addresses: {"addr":"fe80::1aa6:f7ff:fe16:e80b/64"}

IPv6 or IPv4 addresses: {"addr":"192.168.1.65/24"}

Happy coding!

References:

https://www.socketloop.com/tutorials/golang-http-server-example

https://www.socketloop.com/tutorials/golang-detect-os-operating-system

http://stackoverflow.com/questions/11356330/getting-cpu-usage-with-golang?rq=1

https://github.com/shirou/gopsutil

  See also : Golang : Get local IP and MAC address





By Adam Ng

IF you gain some knowledge or the information here solved your programming problem. Please consider donating to the less fortunate or some charities that you like. Apart from donation, planting trees, volunteering or reducing your carbon footprint will be great too.


Advertisement