0

I am trying to calculate the CPU load of a processor using the steps found here. I managed to do this:

cat /proc/stat | head -n 1 | awk '{print ($5+$6, $2+$3+$4+$7+$8+$9)}' | awk '{print($1,$1+$2)}'

This gives me the values I need. However, I need to calculate the same values a second later and then use both of these results to calculate the final load. That means, that I need to do something like this:

cat /proc/stat | calculate something | awk '{print($1,$1+$2)}' ; sleep for a second; calculate again; use both of the results

Is there a way for me to save the variables $1 and $1+$2 in the first awk call, so that I can use them later? I cannot use a bash script, it needs to be done in a command line.

ampersander
  • 208
  • 2
  • 9
  • 1
    `bash script, it needs to be done in a command line` Command line is bash, it's the same. `hat I need to do something` So do exactly that. `a=$(....); sleep 1; b=$(...); echo use $a and $b`. – KamilCuk Feb 26 '22 at 11:45
  • can you expand on your comment: *`it needs to be done in a command line.`*? everytime you need to perform this operation ... are you going to manually type it at the command prompt? wouldn't it make more sense to place it in a script that can be executed repeatedly (without the need to do all that typing, or to introduce syntax/logic errors with manual typing)? even placing the logic into a function (a type of 'script'; see EdMorton's answer) would be of use – markp-fuso Feb 26 '22 at 15:29

2 Answers2

3

You don't need to piece together separate calls to tools in a pipeline for your existing command. This:

cat /proc/stat | head -n 1 | awk '{print ($5+$6, $2+$3+$4+$7+$8+$9)}' | awk '{print($1,$1+$2)}'

can be rewritten as this:

awk 'NR==1{x=$5+$6; print x, x+$2+$3+$4+$7+$8+$9; exit}' /proc/stat

It sounds like what you might want to do is something like:

foo() { awk 'NR==1{x=$5+$6; print x, x+$2+$3+$4+$7+$8+$9; exit}' /proc/stat; }
{ foo; sleep 1; foo; } | awk 'NR==1{ p1=$1; p2=$2; next } { use p1, $1, p2, and $2 }'

If you can't do whatever it is you're trying to do given that information then edit your question to provide clearer requirements and some concise, testable, truly representative sample input/output.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
1

A simple solution would be to create the complete input first and process it with awk next. We first define the cpuLoad bash function to capture two CPU loads with a 1 second interval:

$ cpuLoad () {
    head -n 1 /proc/stat
    sleep 1
    head -n 1 /proc/stat
  }
$ cpuLoad
cpu  8481582 17390 3183770 873720681 403491 0 708461 0 0 0
cpu  8481582 17390 3183774 873721078 403491 0 708461 0 0 0

Then we can feed an awk script that implements the exact algorithm of the accepted answer you cite:

$ cpuLoad | awk '{
    Idle = $5+$6
    NonIdle = $2+$3+$4+$7+$8+$9
    Total = Idle + NonIdle
    totald = Total - PrevTotal
    idled = Idle - PrevIdle
    PrevTotal = Total
    PrevIdle = Idle
  }
  END {
    CPU_Percentage = 100.0 * (totald - idled) / totald
    print CPU_Percentage
  }'
4.987531

But we can simplify a lot:

$ cpuLoad | awk '{
    totald = $2+$3+$4+$5+$6+$7+$8+$9 - totald
    idled = $5+$6 - idled
  }
  END {
    print 100.0 * (totald - idled) / totald
  }'
0.501253

And finally, we can encapsulate all this in the bash function:

$ cpuLoad () {
    { head -n 1 /proc/stat; sleep 1; head -n 1 /proc/stat; } |
    awk '{t = $2+$3+$4+$5+$6+$7+$8+$9 - t; i = $5+$6 - i}
      END {print 100.0 * (t - i) / t}'
  }
$ cpuLoad
0.750000
Renaud Pacalet
  • 25,260
  • 3
  • 34
  • 51
  • That makes a lot of sense. I was too focused on helping the OP implement the solution they asked for and didn't bother to think if there was a better solution. – Ed Morton Feb 28 '22 at 13:07