4

My goal is to create a script which lists top 5 the most memory consuming processes with their PIDs, Mem ifnos and Swap consumed. Partially, I have it done. But now, I would like to make it in one output in bash/awk. Awk doesn't see the passed bash array. Here is my approach:

echo -e "PID\t%CPU\t%MEM\tMEM\tSWAP\tPROCESS"
pids=($(ps aux | awk 'BEGIN { FS = "[ \t]+" } ; {pid[$11]+=$2}; {mem[$11]+=int($6/1024)}; {cpuper[$11]+=$3};{memper[$11]+=$4}; END {for (i in mem) {print " "pid[i]"\t",cpuper[i]"%\t",memper[i]"%\t",mem[i],i}}' | sort -k4nr | head -n 5|awk '{print $1}'))

swap=()
j=0
for i in "${pids[@]}"
do
   :
        if [ -f "/proc/$i/status" ]
        then
                swap[j]=$(awk '/Tgid|VmSwap|Name/{printf $2" "}END{ print ""}' < /proc/$i/status|awk '{print int($3/1024)}')
        else
                swap[j]=0
        fi
        j+=1
done

echo ${swap[@]}

ps aux | awk -v sw="${swap[*]}" -v sep="[:]" 'BEGIN { n = split(sw, a, sep); FS = "[ \t]+" } ; {pid[$11]+=$2}; {mem[$11]+=int($6/1024)}; {cpuper[$11]+=$3};{memper[$11]+=$4}; END {for (i in mem) {print " "pid[i]"\t",cpuper[i]"%\t",memper[i]"%\t",mem[i]" MB\t",a[i]" MB",i}}' | sort -k4nr | head -n 5

The output is

PID     %CPU    %MEM    MEM     SWAP    PROCESS
 57551   6.3%    4.7%    9076 MB          MB java
 478839  1.2%    0%      657 MB   MB /usr/sbin/httpd
 54418   1.6%    0.2%    524 MB   MB /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.121-0.b13.el7_3.x86_64/jre/bin/java
 63047   0.1%    0%      47 MB    MB /usr/sbin/mysqld
 237334  0%      0%      22 MB    MB sshd:

We see that there is a lack of information from table swap which seems to be in var sw splitted to var a.

Szymon Roziewski
  • 956
  • 2
  • 20
  • 36
  • try `swap[j].... awk ... <( /proc/$i/status|awk '{print int($3/1024)}') )` . Good luck. – shellter May 09 '17 at 15:14
  • What do you mean it doesn't see the passed bash array? What output do you get? What are you expecting? – 123 May 09 '17 at 15:32

2 Answers2

6

Here,

awk -v sw="${swap[*]}" -v sep="[:]" 'BEGIN { n = split(sw, a, sep); ... }

You seem to be trying to split sw on colons. But "${swap[*]}" will produce a string with the elements of the array swap joined with the first character of IFS, a space by default.

So you'd need to either change IFS to a colon before using "${swap[*]}", or set the separator to a space on the awk side.

$ arr=(foo bar) ; IFS=:
$ awk -v par="${arr[*]}" 'BEGIN{ n = split(par, a, ":"); 
    for (x in a) {printf "%s %s\n", x, a[x]}; exit }' 
1 foo
2 bar
ilkkachu
  • 6,221
  • 16
  • 30
3

For information ps with some options may give the result

ps -eo pid,%cpu,%mem,vsz,sz,cmd --sort -vsz | head

Also

j=0
j+=1

Works only with typeset -i j

Nahuel Fouilleul
  • 18,726
  • 2
  • 31
  • 36