Reputation: 11
I have this code:
total=0;
ps -u $(whoami) --no-headers | awk {'print $1'} | while read line;
do vrednost=$(pmap $line | tail -n1 | column -t | cut -d" " -f3 | tr "K" " ");
total=$(( vrednost + total ))
echo $total
done
echo total: $total
As you can see, my code sums usage of all my processes. When I echo my total every time in while, it is working ok, but at the end... When i want total to be a value (echo total: $total
) it is still zero. but before (in while
) has right value.
Upvotes: 1
Views: 232
Reputation: 531165
Let's cut down on the number of extra processes you need :)
declare -i total=0
for size in $( ps -u $(whoami) --no-header -o vsz ); do
total+=$size
done
echo $total
First, use various options for ps
to generate the desired list of process sizes, in kilobytes. Iterate over that list using a bash for-loop, keeping a running total in a parameter declared with the 'integer' attribute for easy arithmetic. The desired sum is now in total
, ready for whatever use you need. The sum includes the memory used by the ps
process itself.
Using while
(Dennis' suggestion) and avoiding process substitution (William's suggestion):
ps -u $(whoami) --no-header -o vsz | {
while read -r var; do
((total+=$var))
done
echo $total
}
(For real one-liner, here's a dc
command that I borrowed from https://stackoverflow.com/a/453290/1126841:
ps -u $(whoami) --no-header -o vsz | dc -f - -e '[+z1<r]srz1<rp'
This sum includes the memory used by the ps
and dc
commands themselves.)
Upvotes: 0
Reputation: 212248
Ignacio's answer is fine, but process substitution is not portable. And there is a simpler solution. You need to echo the total in the same subshell in which it is calculated:
... | { while read line; do ...; done; echo total: $total; }
Upvotes: 0
Reputation: 107040
Okay, pick and choose. You can either do it in BASH or AWK, but don't do both. You've seen a BASH example, here's an AWK example:
ps -e -o user -o vsz | awk -v USER="$(whoami)" '
BEGIN {TOTAL = 0}
END {print "Total is " TOTAL}
{
if ($1 == USER) {
TOTAL += $2
}
}
'
Awk is like a programming language that assumes a loop (like perl -n
) and processes each line in the file. Each field (normally separated by whitespace) is given a $
variable. The first is $1
, the second is $2
, etc.
The -v
option allows me to define an awk variable (in this case USER
) before I run awk.
The BEGIN
line is what I want to do before I run my awk
script. In this case, initialize TOTAL
to zero. (NOTE: This really isn't necessary since undefined variables automatically are given a value of zero). The END
line is what I want to do afterwards. In this case, print out my total.
So, if the first field ($1) is equal to my user, I'll add the second field (the vsize) to my total.
All Awk programs are surrounded by {...}
and they usually have single quotes around them to prevent shell interpolation of $1
, etc.
Upvotes: 1
Reputation: 798646
#!/bin/bash
while read ...
do
...
done < <(ps ...)
Upvotes: 3
Reputation: 1334
Try this
#!/bin/bash
total=0;
for line in `ps -u $(whoami) --no-headers | awk {'print $1'}`;
do
vrednost=$(pmap $line | tail -n1 | column -t | cut -d" " -f3 | tr "K" " ");
total=$(( $vrednost + $total ))
echo $total
done
echo "total: $total"
Upvotes: 0