barfatchen barfatchen - 5 months ago 23
Bash Question

Shell script to cut /proc/softirqs

The following is output of "cat /proc/softirqs " :

CPU0 CPU1 CPU2 CPU3
HI: 24 13 7 54
TIMER: 344095632 253285150 121234786 108207697
NET_TX: 2366955 319 695 316044
NET_RX: 16337920 16030558 250497436 117201444
BLOCK: 19631 2747 2353 5067051
BLOCK_IOPOLL: 0 0 0 0
TASKLET: 298 93 157 20965
SCHED: 74354472 28133393 30646119 26217748
HRTIMER: 4123645358 2409060621 2466360502 401470590
RCU: 26083738 17708780 15330534 16857905


My another machine has 24 cpu cores and the output is hard to read ,
I like the output to be only cpu0 , cpu2 , cpu4 , cpu6, ....
I know cut or awk might be ued to do that ,
but no idea how to use it to get even output columns .

Edit :

awk -F" " '{printf("%10s\t%s\n", $2,$4) }'


will get

CPU1 CPU3
24 7
344095632 121234786
2366955 695
16337920 250497436
19631 2353
0 0
298 157
74354472 30646119
4123645358 2466360502
26083738 15330534


unfortunately , CPU1 should be CPU0 , CPU3 should be CPU2 ,
the first line has only 4 columns , may I skip the first line
in this shell ?!

Edit2 :

watch -d "cat /proc/softirqs | awk -F" " '{printf("%10s\t%s\n",$2,$4)}' "


encounter errors like the following :

Every 2.0s: cat /proc/softirqs | awk -F '{print }' Tue Jun 21 10:23:22 2016

Usage: awk [POSIX or GNU style options] -f progfile [--] file ...
Usage: awk [POSIX or GNU style options] [--] 'program' file ...
POSIX options: GNU long options: (standard)
-f progfile --file=progfile
-F fs --field-separator=fs
-v var=val --assign=var=val
Short options: GNU long options: (extensions)
-b --characters-as-bytes
-c --traditional
-C --copyright
-d[file] --dump-variables[=file]
-e 'program-text' --source='program-text'
-E file --exec=file
-g --gen-pot
-h --help
-L [fatal] --lint[=fatal]
-n --non-decimal-data
-N --use-lc-numeric
-O --optimize
-p[file] --profile[=file]
-P --posix
-r --re-interval
-S --sandbox
-t --lint-old
-V --version

To report bugs, see node `Bugs' in `gawk.info', which is
section `Reporting Problems and Bugs' in the printed version.

gawk is a pattern scanning and processing language.
By default it reads standard input and writes standard output.

Examples:
gawk '{ sum += $1 }; END { print sum }' file
gawk -F: '{ print $1 }' /etc/passwd


what else should I try ?!

Edit3 :

The final workable shell would like :

# define function encapsulating code; this prevents any need for extra layers of quoting
# or escaping.
run() {
awk 'NR>1{printf("%20s\t%10s\t%s\n",$1,$2,$4)}' </proc/softirqs|egrep 'TIMER|RX'
}

# export function
export -f run

# run function in subshell of watch, ensuring that that shell is bash
# (other shells may not honor exported functions)
watch -d "bash -c run"

Answer

One easy way to communicate code to a subprocess of watch that avoids escaping errors is to use an exported function:

# define function encapsulating code; this prevents any need for extra layers of quoting
# or escaping.
run() {
  awk -F" " '{printf("%10s\t%s\n",$2,$4)}' </proc/softirqs
}

# export function
export -f run

# run function in subshell of watch, ensuring that that shell is bash
# (other shells may not honor exported functions)
watch "bash -c run"

To avoid the dependency on exported functions, one can also use declare -f to retrieve the function's source in an evalable form, and printf %q to escape it to survive processing by the outer shell invoked by watch:

run() {
  awk -F" " '{printf("%10s\t%s\n",$2,$4)}' </proc/softirqs
}
printf -v run_str '%q' "$(declare -f run); run"
watch "bash -c $run_str"