1

OS: Debian 8 x64

I'd like to log every 5 seconds the CPU percentage into a CSV file in the format below:

YYYY-MM-DD HH:MM:SS,CPU%

I'm not familiar with how to use the top program to calculate the ((us+sy)/(us+sy+id)*100) using awk/grep. Would appreciate help in doing so.

Through my searches, I saw a few examples of people using top -bn1 and top -bn2. However, if my loop is calling top, I'd assume I wouldn't need to use batch mode at all.

Here's the shell script I started to write.

#!/bin/bash

while sleep 5; do "top | grep "Cpu(s)" | awk '{}' >> cpu.csv; done
| improve this question | | | | |
  • 2
    If you're not interested in per-process statistics, you may want to consider the CPU fields of vmstat or mpstat (which can be polled at specified intervals without resorting to an explicit shell loop e.g. vmstat 5 | awk ...) – steeldriver Aug 15 '15 at 22:59
  • How can I do this with vmstat? – linguru772x Aug 15 '15 at 23:06
  • are you limited to top? you can consider using atop instead, it has a batch logging mode – AnonymousLurker Dec 17 '18 at 9:14
1

You can do this via vmstat:

#!/usr/bin/perl

open VMSTAT, "vmstat 5|";
<VMSTAT>; <VMSTAT>; # skip the header
while (<VMSTAT>) {
    @now = split;
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime (time);
    printf "%d-%02d-%02d %02d:%02d:%02d,%d%\n", $year+1900, $mon, $mday, $hour, $min, $sec,
        $now[12] + $now[13];
}

Most of the code is for printing out the date...

| improve this answer | | | | |
0

1) Let's compare the following two versions:

while sleep 0.1 ; do top -d 10 | grep Cpu ; done
#versus batch mode
while sleep 0.1 ; do top -d 10 -bn1 | grep Cpu ; done

You will see that in the first example the time is defined by top's update interval ( set to 10 seconds via -d 10), while in the second the sleep command in the while loop is the limit. Note that also top never finishes in the first example, which makes processing any piped output a problem, as the program that reads from stin never gets a "process ended" signal which especially is a problem for column-based programs like awk or cut. See how e.g.

top -d 0.1 -b | grep Cpu | cut -d' ' -f1

will not produce output at the intervals top produces it, but rather in irregular batches, while

while sleep 0.1 ; do top -bn1 | grep Cpu | cut -d' ' -f1 ; done

produces output at desired intervals.

Long story short: DO use you while loop AND top -bn1

2) awk processing:

With stin read from top -bn1 | grep Cpu, you can use:

awk 'BEGIN { FS == " +" } ; { cmd1="date +%Y-%m-%d" ; cmd2="date +%H:%M:%S" ; while ( cmd1 | getline a ) ; while ( cmd2 | getline b) ; print a,b,($2+$4)/($2+$4+$8)*100"%" }'

As BEGIN { FS == " +" } will use one or more (+) spaces as field separators, the respective fields for us,sy, and id are $2,$4, and $8.

The workaround with cmd1="..." ; while ( cmd1 | getline a) is necessary to read a system call's result as variable in awk. See @ghostdog74's answer here

| improve this answer | | | | |
  • Why is the output always provide the same percentage no matter the current load or stress test? – linguru772x Aug 16 '15 at 2:47
  • I see what's wrong. $2 $4 and $8 are all printing wrong output. Top is showing 0 idle and the script is showing 94% idle. – linguru772x Aug 16 '15 at 3:04
  • hmm, my top -bn1 | grep Cpu output looks like %Cpu(s): 9.7 us, 3.4 sy, 0.0 ni, 70.5 id, 16.2 wa, 0.0 hi, 0.2 si, 0.0 st , so I used $2, $4, and $8. What do those columns show for you? – Fiximan Aug 16 '15 at 11:51
-1

I would say that proposed solutions are overkill. This should do...

echo $(date +'%Y-%m-%d %H:%M:%S,' && uptime | awk '{print "CPU: " $9*100 "%"}' ) >> myfile.csv

Of course put this in while loop together with desired sleep time.

It takes CPU load from "uptime" command, which is equal as "top" load and appends it to a file.

BR, Neven

| improve this answer | | | | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.