Parsing System Info

When I began at Imperial, I inherited management of a fairly large cluster of workstations of various ages and specifications. Every so often, we’ll get some new ones and retire some of the lower spec ones. This is one of the reasons I wanted a quick, command line script to gather useful information about the system and output it in a fairly compact format.

The main things I wanted were details on:

  • The cpu(s) - the model, and the number of cores and how these are laid out including whether these are physical or logical (i.e. whether hyperthreading is on).
    • This can all be found from /proc/cpuinfo but needs to be parsed out.
  • The memory - the total, the layout and the speed.
    • This is a little trickier. The total memory can be found with the free command, but dmidecode is needed for more detailed info but you don’t get anything useful unless you run it as root.
  • The graphics card - the model is enough here.
    • This can be found by parsing the output of the lspci command.
  • Also I figured getting the mac address and local ip for the ethernet connection would be useful for cross checking records.
    • This can be found using the ip command. One awkward thing is the ethernet interface can have various different labels, such as eth0, eno1 or enp4s0f2, so parsing this is a little trickier.

In the end I combined all this into the following bash script, where I swap between using grep, cut and awk for parsing depending on whichever seemed most convenient. The script is also available as a gitlab snippet.

#!/bin/bash
# Script to parse hardware info on a Linux workstation.

cpufile=/proc/cpuinfo
test -f $cpufile || exit 1

echo -n CPU Model: $(grep "model name" $cpufile | sort -u | cut -d : -f 2-)
echo " with$(grep "cache size" $cpufile | sort -u | cut -d : -f 2-) cache."
numphy=$(grep "physical id" $cpufile | sort -u | wc -l)
echo -n "Physical CPUs: ${numphy}.  "
numcore=$(grep "core id" $cpufile | sort -u | wc -l)
echo -n "Cores/CPU: ${numcore}.  "
echo -n "Physical cores: $((numcore * numphy)).  "
numlog=$(grep "processor" $cpufile | wc -l)
echo "Logical cores: ${numlog}."

memtot=$(free -h | grep Mem | awk '{print $2}')
echo -n "Total RAM: ${memtot}."

# The /usr/sbin/dmidecode command can give the number, size and speed of the
# installed RAM, but it must be run as root.
if [[ "$USER" == "root" ]]; then
    raminfo=$(dmidecode --type 17 |\
            awk '/Size/{if ($2!="No") printf "%s %s, ",$2,$3} {if ($1=="Speed:" && $2!="Unknown") print $2" "$3}' |\
            uniq -c)
    echo -n "  Composition:"
    echo "$raminfo" | awk '{if (NF==5) print "  "$1" x "$2" "$3" "$4" "$5"."}'
else
    echo
fi

gcard=$(lspci | awk -F ':' '/VGA/{print $3}')
echo "Graphics:${gcard}."

netinfo=$(ip addr | grep -2 "en[o-p][0-9]\|eth[0-9]" | grep -1 "inet ")
macaddr=$(echo "$netinfo" | awk '/link/{print $2}')
ipaddr=$(echo "$netinfo" | awk '/inet/{print $2}' | awk -F'/' '{print $1}')
echo "Ethernet: MAC Address: ${macaddr}.  IP Address: ${ipaddr}."

I’ve tested this on our Debian systems. The dmidecode package is the only thing I expect you may not have by default.

The output, when run as root looks like the following:

CPU Model: Intel(R) Xeon(R) Gold 6130 CPU @ 2.10GHz with 22528 KB cache.
Physical CPUs: 1.  Cores/CPU: 16.  Physical cores: 16.  Logical cores: 32.
Total RAM: 125G.  Composition:  4 x 32 GB, 2666 MHz.
Graphics: NVIDIA Corporation Device 1cb6 (rev a1).
Ethernet: MAC Address: 12:34:56:78:9a:bc.  IP Address: 123.456.789.10.