0

I'm trying to create a simple bash script to monitor the following: CPU Utilization, outbound network bandwidth, and inbound network bandwidth. The kicker, I have to use information from /proc/loadavg for the CPU and information from /proc for the bandwidth.

For the CPU Utilization, because it is supposed to be on a short time interval, I can use the first value from /proc/loadavg. Thing is, I'm not sure how to just get that one value so what I have so far is this:

CPU=sudo cat /proc/loadavg | sed 's///'
echo "CPU Utilization: $CPU %"

Where I'm not sure what the sed operation should be. Also I'm not sure how to format what I would get from that so that it would print as "16.5%"

For the bandwidth monitors I haven't the slightest clue of what I could use in /proc to get that sort of information so I'm open to all suggestions.

theiwarlock
  • 89
  • 1
  • 8

2 Answers2

3

Load average

You don't need sudo to read /proc/loadavg

In addition, sed is the wrong tool here, try using cut, for example:

$ cut -d' ' -f1 < /proc/loadavg
0.04

cut will cut lines by a delimiter (given with -d), in this case a space, and you can then use -f to select a field, in this case the first one.

Now, converting it to percentages is actually fairly meaningless, since you'll often end up above 100% (see comment below), I've seen load averages in excess of 50 (that would be 5000% percent?).
In all my years of UNIX/Linux experience, I can't recall ever seeing the load average being expressed as a percentage, and if I would encounter such a thing, I would find it very odd.

But if you really want to (you don't!), just multiply by 100 with dc, like so:

$ dc -e "`cut -d' ' -f1 < /proc/loadavg` 100 * p"
29.00

For the CPU Utilization, because it is supposed to be on a short time interval, I can use the first value from /proc/loadavg.

The load average is not the same thing as CPU usage.

  • A load average of 1 means there is one process waiting for something (usually the CPU or disk).
  • A load average of 2 means there are two processes waiting.
  • A load average of 0.5 (over the last minute), can mean that for 30 seconds, there was one process waiting, and for 30 seconds, there were no processes waiting. It can also mean that for 15 seconds there were two processes waiting, and for 45 seconds there were no processes waiting. The keyword here is average.

If you want to get the CPU utilization, then this is probably the most portable way:

$ top -bn2 | grep "Cpu(s)" | \
           tail -n1 | \
           sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | \
           awk '{print 100 - $1"%"}'

Note you need to use -n2 to get fairly accurate results.

I've adapted this from this answer, which also lists some other possibilities, some simpler, but most tools mentioned aren't installed by default on most systems.

Network

For the bandwidth monitors I haven't the slightest clue of what I could use in /proc to get that sort of information so I'm open to all suggestions.

You can use the output of ifconfig, for example, on my system:

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.178.28  netmask 255.255.255.0  broadcast 192.168.178.255
        inet6 2001:980:82cd:1:20c:29ff:fe9e:c84b  prefixlen 128  scopeid 0x0<global>
        inet6 fe80::20c:29ff:fe9e:c84b  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:9e:c8:4b  txqueuelen 1000  (Ethernet)
        RX packets 45891  bytes 36176865 (34.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 20802  bytes 2603821 (2.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

It's the RX packets & TX packets we want. Let's extract just those values:

$ ifconfig ens33 | grep -E '(R|T)X packets' | grep -Eo '\([0-9].*\)' | tr -d '()'
34.5 MiB
2.5 MiB
  • First we grep all the lines starting with RX or TX
  • With those lines, we then grep for a parenthesis \(, followed by a number [0-9], followed by any characters .*, followed by a closing parenthesis \). With the -o flag we show only the matching part, instead of the whole line.
  • With tr, we remove the unwanted parentheses.

This should be what you want. If you want to get a number of bytes, you can use a different grep pattern in the second grep. I'll leave it as an exercise to you what exactly that is.

Community
  • 1
  • 1
Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
  • +1; nice job; so is there a [fairly easily scriptable] way to get a _CPU utilization percentage_ figure? Is there a way to use `\proc` to get bandwidth figures, as the OP suggests? – mklement0 Feb 19 '14 at 00:33
  • @mklement0 I'm not aware of anything in `/proc` that gets the bandwidth usage, and for completion's sake I've updated my answer regarding the CPU utilization. – Martin Tournoij Feb 19 '14 at 01:01
  • 1
    Thanks; the CPU utilization code doesn't work as intended; if you use `-n2`, you'll get *two* output lines from the `grep` command, so I presume you only meant use the second. Also, the command appears to be written for systems where `top -v` returns `procps-ng` (e.g., Fedora). There's also `procps`, found on, e.g., Ubuntu and CentOS, where the command doesn't work (always indicates 100%, because parsing fails due to the line with the CPU figures being formatted differently). (cont'd below) – mklement0 Feb 19 '14 at 03:26
  • 1
    Here's a version that works on both implementations: `top -b -n2 | fgrep "Cpu(s)" | tail -1 | awk -F'id,' '{ split($1, vs, " "); v=vs[length(vs)]; sub("%", "", v); printf "%.1f%%\n", 100 - v }'` – mklement0 Feb 19 '14 at 03:27
  • @mklement0 Oops, I forgot to copy/paste the `tail` I used in testing >.< ... Also, wasn't aware of different `top` versions in Linux, thanks! You should post your solution to [the question I linked](http://stackoverflow.com/questions/9229333/how-to-get-overall-cpu-usage-e-g-57-on-linux). – Martin Tournoij Feb 20 '14 at 22:14
  • Minor update to the above - when the CPU is reported as 100% idle, the above command doesn't work; here's the corrected version: `top -b -n2 -p 1 | fgrep "Cpu(s)" | tail -1 | awk -F'id,' -v prefix="$prefix" '{ split($1, vs, ","); v=vs[length(vs)]; sub("%", "", v); printf "%s%.1f%%\n", prefix, 100 - v }'` – mklement0 Feb 21 '14 at 04:18
1

Here's how you can print the first number output by cat /proc/loadavg as a percent value (but see @Carpetsmoker's caveat regarding whether that makes sense), rounded to 1 decimal place:

 printf "1-minute load average: %.1f%%\n" \
   $(bc <<<"$(cut -d ' ' -f 1 /proc/loadavg) * 100")
mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Load average is *not* "CPU Utilization"! It is something fundamentally different. – Martin Tournoij Feb 18 '14 at 23:55
  • @Carpetsmoker: Fair point - I was just reusing the OP's string and focusing on the calculation part - corrected to reflect what is actually being reported – mklement0 Feb 19 '14 at 00:07