Search code examples
shellawkcut

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"

Solution

  • 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"