I am fairly new to shell scripting so kindly bear with me. Here is what I want to do : Check the sar logs captured on a Linux server and if the load average for the past 1 minute is greater than the number of CPUs, print that load info. I used the following command for this:
awk '/runq-sz/,/$^/' /var/log/sa/sar* | awk '{print $5}' \
| awk '{if ($1 > **CPU_COUNT**) print $0}' \
| grep -iv "ldavg" | head -n5
Ex, for a server with 16 CPUs:
awk '/runq-sz/,/$^/' /var/log/sa/sar* | awk '{print $5}' \
| awk '{if ($1 > **16**) print $0}' | grep -iv "ldavg" \
| head -n5
I get the following output which is correct and shows the command is working.
18.11
73.91
40.03
40.77
33.85
But what if instead of hardcoding CPU_COUNT, use a built-in Linux command like nproc? Is it possible to do so? If yes, how do I use it? I tried with something like this:
awk '/runq-sz/,/$^/' /var/log/sa/sar* | awk '{print $5}' \
| awk '{if ($1 > echo "$(nproc)") print $0}' \
| grep -iv "ldavg"
But it doesn’t appear to be working. Am I missing something here? If this approach is incorrect how do I change the command?
You’re on the right track, but you’re trying to use echo $(nproc)
within awk
, which won’t work as expected. You need to pass the output of nproc
to awk
as a variable. You can do this using the -v option in awk. Here’s how you can modify your command:
awk -v cpu_count=$(nproc) '/runq-sz/,/$^/' /var/log/sa/sar* | awk -v cpu_count="$cpu_count" '{if ($1 > cpu_count) print $0}' | grep -iv "ldavg" | head -n5
This should give you the desired output, with the number of CPUs dynamically determined by nproc
.
Does this answer your question? How do I use shell variables in an awk script?
do something like
amount=$(....command-to-get-n-count...)
and then pass that one to awk as shown in the marked duplicate.if N > echo....
is certainly not a valid numeric comparision inawk
. Have a look at awk’s-v
option, which allows you to set awk variables when invoking awk.You don’t need all those separate commands and pipelines for this, just 1 awk command will do. Post a minimal reproducible example including concise, testable sample input and expected output so we can help you do this the right way.
BTW, it’s pretty much never necessary to pipe from awk to
grep
orhead
; awk itself can do the work of both those tools. In the case of grep, use/ldavg/ {next}
to skip lines that containldavg
; in the case ofhead
, useNR > 5 { exit }