Bash: wait until CPU usage gets below a threshold - linux

In a bash script I need to wait until CPU usage gets below a threshold.
In other words, I'd need a command wait_until_cpu_low which I would use like this:
# Trigger some background CPU-heavy command
wait_until_cpu_low 40
# Some other commands executed when CPU usage is below 40%
How could I do that?
Edit:
target OS is: Red Hat Enterprise Linux Server release 6.5
I'm considering the average CPU usage (across all cores)

A much more efficient version just calls mpstat and awk once each, and keeps them both running until done; no need to explicitly sleep and restart both processes every second (which, on an embedded platform, could add up to measurable overhead):
wait_until_cpu_low() {
awk -v target="$1" '
$13 ~ /^[0-9.]+$/ {
current = 100 - $13
if(current <= target) { exit(0); }
}' < <(LC_ALL=C mpstat 1)
}
I'm using $13 here because that's where idle % is for my version of mpstat; substitute appropriately if yours differs.
This has the extra advantage of doing floating point math correctly, rather than needing to round to integers for shell-native math.

wait_for_cpu_usage()
{
current=$(mpstat 1 1 | awk '$12 ~ /[0-9.]+/ { print int(100 - $12 + 0.5) }')
while [[ "$current" -ge "$1" ]]; do
current=$(mpstat 1 1 | awk '$12 ~ /[0-9.]+/ { print int(100 - $12 + 0.5) }')
sleep 1
done
}
Notice it requires sysstat package installed.

You might use a function based on the top utility. But note, that doing so is not very reliable because the CPU utilization might - rapidly - change at any time. Meaning that just because the check succeeded, it is not guaranteed that the CPU utilization will stay low as long the following code runs. You have been warned.
The function:
function wait_for_cpu_usage {
threshold=$1
while true ; do
# Get the current CPU usage
usage=$(top -n1 | awk 'NR==3{print $2}' | tr ',' '.')
# Compared the current usage against the threshold
result=$(bc -l <<< "$usage <= $threshold")
[ $result == "1" ] && break
# Feel free to sleep less than a second. (with GNU sleep)
sleep 1
done
return 0
}
# Example call
wait_for_cpu_usage 25
Note that I'm using bc -l for the comparison since top prints the CPU utilization as a float value.

As noted by "Mr. Llama" in a comment above, I've used uptime to write my simple function:
function wait_cpu_low() {
threshold=$1
while true; do
current=$(uptime | awk '{ gsub(/,/, ""); print $10 * 100; }')
if [ $current -lt $threshold ]; then
break;
else
sleep 5
fi
done
}
In awk expression:
$10 is to get average CPU usage in last minute
$11 is to get average CPU usage in last 5 minutes
$12 is to get average CPU usage in last 15 minutes
And here is an usage example:
wait_cpu_low 20
It waits one minute average CPU usage is below 20% of one core of CPU.

Related

How to find more than one process pinned to the same core?

$ lsisolcpus
core pid foreign comm cmdline
30 27213 2147 Test1 ./Test1
30 27214 2157 Test2 ./Test2
I use lsisolcpus to find cores used by different processes.
Question> Is there a way that I can automatically detect when more than one process is pinned to the same cpu core? In above example, I would like to see the script complains that there is a conflict because both Test1 and Test2 are pinned to the core 30.
How about:
lsisolcpus | awk 'NR==1 {next} { cpus[$1][$4]="" } END { for ( i in cpus) { cnt=0;for (n in cpus[i]) {cnt++} if (cnt>1) { print "WARNING - conflict on core - "i;for (o in cpus[i]) { print o } } } }'
Taking the output of the lsisolcpus command and feeding it into awk. We ignore the first line of the output (NR==1) and then build a 2 dimensional array of the output (cpus) indexed by core and command. We then loop through the array and then if there is more than one entry for each core (cnt>1), we print an error message and the commands tied to that core.

Processing text in bash - extracting the volume of a program from pactl sink-inputs output

Looking for a way to extract the volume from
pactl list sink-inputs
Output example:
Sink Input #67
Driver: protocol-native.c
Owner Module: 12
Client: 32
Sink: 0
Sample Specification: s16le 2ch 44100Hz
Channel Map: front-left,front-right
Format: pcm, format.sample_format = "\"s16le\"" format.channels = "2" format.rate = "44100" format.channel_map = "\"front-left,front-right\""
Corked: no
Mute: no
Volume: front-left: 19661 / 30% / -31.37 dB, front-right: 19661 / 30% / -31.37 dB
balance 0.00
Buffer Latency: 100544 usec
Sink Latency: 58938 usec
Resample method: n/a
Properties:
media.name = "'Alerion' by 'Asking Alexandria'"
application.name = "Clementine"
native-protocol.peer = "UNIX socket client"
native-protocol.version = "32"
media.role = "music"
application.process.id = "16924"
application.process.user = "gray"
application.process.host = "gray-kubuntu"
application.process.binary = "clementine"
application.language = "en_US.UTF-8"
window.x11.display = ":0"
application.process.machine_id = "54f542f950a5492c9c335804e1418e5c"
application.process.session_id = "3"
application.icon_name = "clementine"
module-stream-restore.id = "sink-input-by-media-role:music"
media.title = "Alerion"
media.artist = "Asking Alexandria"
I want to extract the
30
from the line
Volume: front-left: 19661 / 30% / -31.37 dB, front-right: 19661 / 30% / -31.37 dB
Note: There may be multiple sink inputs, and I need to extract the volume only from Sink Input #67
Thanks
P.S. Need this for a script of mine which should increase or decrease the volume of my music player. I'm completely new to both linux and bash so I couldn't figure a way to resolve the problem.
Edit:
My awk version
gray#gray-kubuntu:~$ awk -W version
mawk 1.3.3 Nov 1996, Copyright (C) Michael D. Brennan
compiled limits:
max NF 32767
sprintf buffer 2040
Since you are pretty new to use standard text processing tools, I will provide an answer with a detailed explanation. Feel free to use it for future.
Am basing this answer using the GNU Awk I have installed which should likely also work in mawk installed in your system.
pactl list sink-inputs | \
mawk '/Sink Input #67/{f=1; next} f && /Volume:/{ n=split($0,matchGroup,"/"); val=matchGroup[2]; gsub(/^[[:space:]]+/,"",val); gsub(/%/,"",val); print val; f=0}'
Awk processes one line at a time which is based on a /pattern/{action1; action2} syntax. In our case though, we match the line /Sink Input #67/ and enable a flag(f) to mark the next occurrence of Volume: string in the lines below. Without the flag set it could match the instances for other sink inputs.
So once we match the line, we split the line using the de-limiter / and get the second matched element which is stored in the array(matchGroup). Then we use the gsub() calls twice once, to replace the leading white-spaces and other to remove the % sign after the number.
This script I wrote might be what you wanted. It lets me adjust the volume easily using the pacmd and pactl commands. Seems to work well when I'm using a GNOME desktop, (Wayland or Xorg), and it's working on RHEL/Fedora and Ubuntu so far. I haven't tried using it with other desktops/distros, or with surround sound systems, etc.
Drop it in your path, and run it without any values to see the current volume. Alternatively set the volume by passing it a percentage. A single value sets both speakers, two values will set left, and right separately. In theory you shouldn't use a value outside of 0%-200%, but the script doesn't check for that (and neither does PulseAudio apparently), so be careful, as a volume higher than 200% may harm your speakers.
[~]# volume
L R
20% 20%
[~]# volume 100% 50%
[~]# volume
L R
100% 50%
[~]# volume 80%
[~]# volume
L R
80% 80%
#!/bin/bash
[ ! -z "$1" ] && [ $# -eq 1 ] && export LVOL="$1" && export RVOL="$1"
[ ! -z "$1" ] && [ ! -z "$2" ] && [ $# -eq 2 ] && export LVOL="$1" && export RVOL="$2"
SINK=$(pacmd list-sinks | grep -e '* index:' | grep -Eo "[0-9]*$")
if [ -z "$LVOL" ] || [ -z "$RVOL" ]; then
# pacmd list-sinks | grep -e '* index:' -A 20 | grep -e 'name:' -e '^\s*volume:.*\n' -e 'balance' --color=none
printf "%-5s%-4s\n%-5s%-4s\n" "L" "R" $(pacmd list-sinks | grep -e '* index:' -A 20 | grep -e '^\s*volume:.*\n' --color=none | grep -Eo "[0-9]*%" | tr "\n" " " | sed "s/ $/\n/g")
exit 0
elif [[ ! "$LVOL" =~ ^[0-9]*%$ ]] || [[ ! "$RVOL" =~ ^[0-9]*%$ ]]; then
printf "The volume should specified as a percentage, from 0%% to 200%%.\n"
exit 1
elif [ "$SINK" == "" ]; then
printf "Unable to find the default sound output.\n"
exit 1
fi
pactl -- set-sink-volume $SINK $LVOL $RVOL

Adding idle workstation to cluster when not used

We have multiple computers in our company that sometimes used as work stations and sometimes as server (running user defined jobs)
I would like to harnessed all the available computing power of the workstations to be part of the grid (to add them to the dedicated servers)
Each grid client can work in one of two modes low (30%) and high (100%) -(the max percentage of cpu and ram that is allocated to the grid client)
The user should not be effected by it, the moment the user starts using the computer (locally or remotely) the client switch to low mode (30%)
after the user is idle for configured time, for example 5 minuets, and the cpu usage is low (no running tasks) the client should switch to high mode
Here is the solution i made based on few examples i found in stackoverflow:
time since screen idle
time since last console action based on "who"
cpu usage of user based on top
to enter the idle state and setting the mode to high mode i wait for idle time in cmd and screen, and require a limited cpu usage,
to exit from high mode any action via cmd or screen will set it back to low mode
#!/bin/bash
idle=false
idleAfter=300 # consider idle after 300 seconds
idleCpuAfter=100 # max cpu usage to enter high mode
idleCpuCount=10 #seconds to keep idle state(without interruptions) before starting high mode
count=0 #count for idle state, when counter reach idleCpuCount client will initiate high mode
while true; do
idleInSecondsCmd=$( who -s | perl -lane 'print "$F[0]\t" . 86400 * -A "/dev/$F[1]"'| sort -k2 -n | head -1 | cut -f2 )
idleInSecondsScreen=$(./getIdle)
cpuLoad=$(top -b -n 1 -u "$user" | awk 'NR>7 { sum += $9; } END { print user, sum; }')
echo "idleInSecondsCmd " + $idleInSecondsCmd # just for debug purposes.
echo "idleInSecondsScreen" + $idleInSecondsScreen # just for debug purposes.
echo "cpuLoad" + $cpuLoad # just for debug purposes.
if [[ ($idleInSecondsCmd -gt $idleAfter)
&& ($idleInSecondsScreen -gt $idleAfter)
&& ($(bc <<< "$cpuLoad <= $idleCpuAfter") -eq 1 )
&& $idle = false ]] ;then
count=$((count + 1))
echo $count
else
count=0
fi
if [[ $idle = false && ($count -gt $idleCpuCount) ]]; then
idle=true
setupLoad.sh 100
fi
if [[ ( $idleInSecondsCmd -lt $idleAfter
|| $idleInSecondsScreen -lt $idleAfter)
&& $idle = true ]] ; then
idle=false
setupLoad.sh 30
fi
sleep 1 # polling interval
done
is it the best approach?

expect , need to treat expression and print results on screen

Guys i have the following problem , i'm issuing the command free in a busybox host , i wanna check how much memory i have free, i need to print if the result is bigger than 10M then i should return something like " i have more than 30M free" etc... i dont know how to treat the output from expect.
i have the code snippet
expect "$"
send "df -h\r"
expect "$"
send "uptime\r"
expect "$"
send "free | awk -F ' ' ' FNR == 2 {print \$3}'\r"
expect "$"
how to treat the output from the command free ? that output would give me integer with the free memory i need to analyze a condition.
You might want check if the Busybox version of free is the same as GNU, but on my Fedora system, free's output looks like
total used free shared buffers cached
Mem: 3094900 2691252 403648 0 442924 983336
-/+ buffers/cache: 1264992 1829908
Swap: 2064380 126268 1938112
To get free memory, this would do it:
free | awk -F ' ' ' FNR == 2 {print \$4}'
To capture Expect output in a tcl variable:
set results $expect_out(buffer)
So the way to do what you want is approximately
send "free | awk -F ' ' ' FNR == 2 {print \$4}'\r"
set freeram $expect_out(buffer)
if { $freeram >= 10000 } {
puts "You have lots of free memory.\n"
}
Since you're using a Linux variant (remotely), the easiest way to get the amount of free memory over ssh is to not use free. Instead, you can use a different approach entirely:
spawn ssh $user#$theOtherHost cat /proc/meminfo
expect {
-re {MemTotal:\s+(\d+) kB} {
set total $expect_out(1,string)
exp_continue
}
-re {MemFree:\s+(\d+) kB} {
set free $expect_out(1,string)
exp_continue
}
"Password:" {
send "$thePassword\r"
exp_continue
}
eof {
# Do nothing; default fall-through is fine
}
}
puts "usage was $free out of $total (both in kilobytes)"

Accurate calculation of CPU usage given in percentage in Linux?

It's a question which has been asked many times, however there is no well supported answer I could find.
Many people suggest the use of top command, but if you run top once (because you have a script for example collecting Cpu usage every 1 second) it will always give the same Cpu usage result (example 1, example 2).
A more accurate way to calculate CPU usage, is by reading the values from /proc/stat, but most of the answers use only the first 4 fields from /proc/stat to calculate it (one example here).
/proc/stat/ has 10 fields per CPU core as of Linux kernel 2.6.33!
I also found this Accurately Calculating CPU Utilization in Linux using /proc/stat question which is pointing out the same issue, -that most other questions only take into consideration 4 out of the many fields- but still the answer given here starts with "I think" (not certain), and except that, it is only concerned about the first 7 fields (out of 10 in /proc/stat/)
This perl script uses all of the fields to calculate the CPU usage, which again I do not think is correct after some further investigation.
After taking a quick look into the kernel code here, it looks like, for example, guest_nice and guest fields are always increasing together with nice and user (so they should not be included in the cpu usage calculation, since they are included in nice and user fields already)
/*
* Account guest cpu time to a process.
* #p: the process that the cpu time gets accounted to
* #cputime: the cpu time spent in virtual machine since the last update
* #cputime_scaled: cputime scaled by cpu frequency
*/
static void account_guest_time(struct task_struct *p, cputime_t cputime,
cputime_t cputime_scaled)
{
u64 *cpustat = kcpustat_this_cpu->cpustat;
/* Add guest time to process. */
p->utime += cputime;
p->utimescaled += cputime_scaled;
account_group_user_time(p, cputime);
p->gtime += cputime;
/* Add guest time to cpustat. */
if (task_nice(p) > 0) {
cpustat[CPUTIME_NICE] += (__force u64) cputime;
cpustat[CPUTIME_GUEST_NICE] += (__force u64) cputime;
} else {
cpustat[CPUTIME_USER] += (__force u64) cputime;
cpustat[CPUTIME_GUEST] += (__force u64) cputime;
}
}
So to sum up, what is an accurate way to calculate the CPU usage in Linux and which fields should be considered in the calculations and how (which fields are attributed to the idle time and which fields to non-idle time)?
According the htop source code, my assumptions looks like they are valid:
(see static inline double LinuxProcessList_scanCPUTime(LinuxProcessList* this) function at LinuxProcessList.c)
// Guest time is already accounted in usertime
usertime = usertime - guest; # As you see here, it subtracts guest from user time
nicetime = nicetime - guestnice; # and guest_nice from nice time
// Fields existing on kernels >= 2.6
// (and RHEL's patched kernel 2.4...)
unsigned long long int idlealltime = idletime + ioWait; # ioWait is added in the idleTime
unsigned long long int systemalltime = systemtime + irq + softIrq;
unsigned long long int virtalltime = guest + guestnice;
unsigned long long int totaltime = usertime + nicetime + systemalltime + idlealltime + steal + virtalltime;
And so, from fields listed in the first line of /proc/stat: (see section 1.8 at documentation)
user nice system idle iowait irq softirq steal guest guest_nice
cpu 74608 2520 24433 1117073 6176 4054 0 0 0 0
Algorithmically, we can calculate the CPU usage percentage like:
PrevIdle = previdle + previowait
Idle = idle + iowait
PrevNonIdle = prevuser + prevnice + prevsystem + previrq + prevsoftirq + prevsteal
NonIdle = user + nice + system + irq + softirq + steal
PrevTotal = PrevIdle + PrevNonIdle
Total = Idle + NonIdle
# differentiate: actual value minus the previous one
totald = Total - PrevTotal
idled = Idle - PrevIdle
CPU_Percentage = (totald - idled)/totald
The following is a bash script which is based on Vangelis's answer. It produces output like this:
total 49.1803
cpu0 14.2857
cpu1 100
cpu2 28.5714
cpu3 100
cpu4 30
cpu5 25
Create a file called get_cpu_usage.sh
Run it using the following command: bash get_cpu_usage.sh 0.2
The argument is the number of seconds to measure. In this case it's 200 milliseconds.
The contents are:
#!/bin/sh
sleepDurationSeconds=$1
previousDate=$(date +%s%N | cut -b1-13)
previousStats=$(cat /proc/stat)
sleep $sleepDurationSeconds
currentDate=$(date +%s%N | cut -b1-13)
currentStats=$(cat /proc/stat)
cpus=$(echo "$currentStats" | grep -P 'cpu' | awk -F " " '{print $1}')
for cpu in $cpus
do
currentLine=$(echo "$currentStats" | grep "$cpu ")
user=$(echo "$currentLine" | awk -F " " '{print $2}')
nice=$(echo "$currentLine" | awk -F " " '{print $3}')
system=$(echo "$currentLine" | awk -F " " '{print $4}')
idle=$(echo "$currentLine" | awk -F " " '{print $5}')
iowait=$(echo "$currentLine" | awk -F " " '{print $6}')
irq=$(echo "$currentLine" | awk -F " " '{print $7}')
softirq=$(echo "$currentLine" | awk -F " " '{print $8}')
steal=$(echo "$currentLine" | awk -F " " '{print $9}')
guest=$(echo "$currentLine" | awk -F " " '{print $10}')
guest_nice=$(echo "$currentLine" | awk -F " " '{print $11}')
previousLine=$(echo "$previousStats" | grep "$cpu ")
prevuser=$(echo "$previousLine" | awk -F " " '{print $2}')
prevnice=$(echo "$previousLine" | awk -F " " '{print $3}')
prevsystem=$(echo "$previousLine" | awk -F " " '{print $4}')
previdle=$(echo "$previousLine" | awk -F " " '{print $5}')
previowait=$(echo "$previousLine" | awk -F " " '{print $6}')
previrq=$(echo "$previousLine" | awk -F " " '{print $7}')
prevsoftirq=$(echo "$previousLine" | awk -F " " '{print $8}')
prevsteal=$(echo "$previousLine" | awk -F " " '{print $9}')
prevguest=$(echo "$previousLine" | awk -F " " '{print $10}')
prevguest_nice=$(echo "$previousLine" | awk -F " " '{print $11}')
PrevIdle=$((previdle + previowait))
Idle=$((idle + iowait))
PrevNonIdle=$((prevuser + prevnice + prevsystem + previrq + prevsoftirq + prevsteal))
NonIdle=$((user + nice + system + irq + softirq + steal))
PrevTotal=$((PrevIdle + PrevNonIdle))
Total=$((Idle + NonIdle))
totald=$((Total - PrevTotal))
idled=$((Idle - PrevIdle))
CPU_Percentage=$(awk "BEGIN {print ($totald - $idled)/$totald*100}")
if [[ "$cpu" == "cpu" ]]; then
echo "total "$CPU_Percentage
else
echo $cpu" "$CPU_Percentage
fi
done
Hey i was also researching for the topic and found this thread really helpful. I used Vangelis Tasoulas formula to write a small python script for this. Attached is my Python code for the issue. It loads the cpu usage per cpu_id every second. Maybe its helps others as well. Also comments/suggestions are welcome :-)
#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
Created on 04.12.2014
#author: plagtag
'''
from time import sleep
import sys
class GetCpuLoad(object):
'''
classdocs
'''
def __init__(self, percentage=True, sleeptime = 1):
'''
#parent class: GetCpuLoad
#date: 04.12.2014
#author: plagtag
#info:
#param:
#return: CPU load in percentage
'''
self.percentage = percentage
self.cpustat = '/proc/stat'
self.sep = ' '
self.sleeptime = sleeptime
def getcputime(self):
'''
http://stackoverflow.com/questions/23367857/accurate-calculation-of-cpu-usage-given-in-percentage-in-linux
read in cpu information from file
The meanings of the columns are as follows, from left to right:
0cpuid: number of cpu
1user: normal processes executing in user mode
2nice: niced processes executing in user mode
3system: processes executing in kernel mode
4idle: twiddling thumbs
5iowait: waiting for I/O to complete
6irq: servicing interrupts
7softirq: servicing softirqs
#the formulas from htop
user nice system idle iowait irq softirq steal guest guest_nice
cpu 74608 2520 24433 1117073 6176 4054 0 0 0 0
Idle=idle+iowait
NonIdle=user+nice+system+irq+softirq+steal
Total=Idle+NonIdle # first line of file for all cpus
CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal)
'''
cpu_infos = {} #collect here the information
with open(self.cpustat,'r') as f_stat:
lines = [line.split(self.sep) for content in f_stat.readlines() for line in content.split('\n') if line.startswith('cpu')]
#compute for every cpu
for cpu_line in lines:
if '' in cpu_line: cpu_line.remove('')#remove empty elements
cpu_line = [cpu_line[0]]+[float(i) for i in cpu_line[1:]]#type casting
cpu_id,user,nice,system,idle,iowait,irq,softrig,steal,guest,guest_nice = cpu_line
Idle=idle+iowait
NonIdle=user+nice+system+irq+softrig+steal
Total=Idle+NonIdle
#update dictionionary
cpu_infos.update({cpu_id:{'total':Total,'idle':Idle}})
return cpu_infos
def getcpuload(self):
'''
CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal)
'''
start = self.getcputime()
#wait a second
sleep(self.sleeptime)
stop = self.getcputime()
cpu_load = {}
for cpu in start:
Total = stop[cpu]['total']
PrevTotal = start[cpu]['total']
Idle = stop[cpu]['idle']
PrevIdle = start[cpu]['idle']
CPU_Percentage=((Total-PrevTotal)-(Idle-PrevIdle))/(Total-PrevTotal)*100
cpu_load.update({cpu: CPU_Percentage})
return cpu_load
if __name__=='__main__':
x = GetCpuLoad()
while True:
try:
data = x.getcpuload()
print data
except KeyboardInterrupt:
sys.exit("Finished")
idnt.net has a good description for how to use the /proc/stat cpu data, include a bash-script for extracting cpu and description of the lines. I just wanted to link it here, since I found it valuable.
I was also looking for the same. Here is my ruby program based on the Vangelis Tasoulas's answer:
#!/usr/bin/env ruby
$VERBOSE = true
prev_file = IO.readlines(::File.join('', 'proc', 'stat')).select { |line| line.start_with?('cpu') }
Kernel.sleep(0.05)
file = IO.readlines(::File.join('', 'proc', 'stat')).select { |line| line.start_with?('cpu') }
file.size.times do |i|
data, prev_data = file[i].split.map(&:to_f), prev_file[i].split.map(&:to_f)
%w(user nice sys idle iowait irq softirq steal).each_with_index do |el, index|
eval "##{el}, #prev_#{el} = #{data[index + 1]}, #{prev_data[index + 1]}"
end
previdle, idle = #prev_idle + #prev_iowait, #idle + #iowait
totald = idle + (#user + #nice + #sys + #irq + #softirq + #steal) -
(previdle + (#prev_user + #prev_nice + #prev_sys + #prev_irq + #prev_softirq + #prev_steal))
puts "CPU #{i}: #{((totald - (idle - previdle)) / totald * 100).round(2)} %"
end
The following is a bash script builds on Fidel's answer and arberg's link.
I wanted to lower the usage of cat awk grep and date calls and spend less cpu usage trying to figure out the cpu usage.
Output:
total: 4%
cpu0: 10%
cpu1: 5%
cpu2: 1%
cpu3: 1%
create a bash script using this:
#!/bin/bash
# Paramiter one used to set time in sec between reads
sleepDurationSeconds=$1
# read cpu stats to arrays
readarray -t previousStats < <( awk '/^cpu /{flag=1}/^intr/{flag=0}flag' /proc/stat )
sleep $sleepDurationSeconds
readarray -t currentStats < <( awk '/^cpu /{flag=1}/^intr/{flag=0}flag' /proc/stat )
# loop through the arrays
for i in "${!previousStats[#]}"; do
# Break up arrays 1 line sting into an array element for each item in string
previousStat_elemant_array=(${previousStats[i]})
currentStat_elemant_array=(${currentStats[i]})
# Get all columns from user to steal
previousStat_colums="${previousStat_elemant_array[#]:1:7}"
currentStat_colums="${currentStat_elemant_array[#]:1:7}"
# Replace the column seperator (space) with +
previous_cpu_sum=$((${previousStat_colums// /+}))
current_cpu_sum=$((${currentStat_colums// /+}))
# Get the delta between two reads
cpu_delta=$((current_cpu_sum - previous_cpu_sum))
# Get the idle time Delta
cpu_idle=$((currentStat_elemant_array[4]- previousStat_elemant_array[4]))
# Calc time spent working
cpu_used=$((cpu_delta - cpu_idle))
# Calc percentage
cpu_usage=$((100 * cpu_used / cpu_delta))
# Get cpu used for calc cpu percentage used
cpu_used_for_calc="${currentStat_elemant_array[0]}"
if [[ "$cpu_used_for_calc" == "cpu" ]]; then
echo "total: "$cpu_usage"%"
else
echo $cpu_used_for_calc": "$cpu_usage"%"
fi
done

Resources