On 2007-12-17 06:00, Patrick Dung [EMAIL PROTECTED] wrote:
I have correction with the script but still doesn't work:
#!/usr/local/bin/bash
for user in `ps -A -o user | sort | uniq | tail +2`
do
echo user: $user
ps aux -U $user | tail +2 | while read line
do
mem=`echo $line | awk {'print $4'}`
echo mem: $mem
TMPSUMMEM=`awk -v x=$mem -v y=$TMPSUMMEM 'BEGIN{printf
%.2f\n,x+y}'`
echo summem: $TMPSUMMEM
done
echo finalsummem: $SUMMEM
export SUMMEM=$TMPSUMMEM
done
echo finalsummem: $SUMMEM
There are *many* race conditions in that script. For example, there's
no guarantee that once you get a snapshot of the ps -A -o user output,
then the same users will be listed in the loop you are running for each
username.
The script is also a bit 'sub-optimal' because it calls ps(1) and parses
its output many times (at least as many times as there are users). A
much better way to `design' something like this would be to keep a hash
of the usernames, and keep incrementing the hash entry for each user as
you hit ps(1) output lines.
I'm not going to even bother writing a script to use a hash in bash(1),
because there are much better languages to work with hashes,
dictionaries or even simple arrays.
Here's for example a Python script which does what I described:
1 #!/usr/bin/env python
2
3 import os
4 import re
5 import sys
6
7 try:
8 input = os.popen('ps xauwww', 'r')
9 except:
10 print Cannot open pipe for ps(1) output
11 sys.exit(1)
12
13 # Start with an empty dictionary.
14 stats = {}
15
16 # Regexp to strip the ps(1) output header.
17 header = re.compile('USER')
18
19 for line in input.readlines():
20 if header.match(line):
21 continue
22 fields = line.split()
23 if not fields or len(fields) 4:
24 continue
25
26 (username, mem) = (fields[0], float(fields[3]))
27 value = None
28 try:
29 value = stats[username]
30 except KeyError:
31 pass
32
33 if not value:
34 stats[username] = 0.0
35 stats[username] += mem
36
37 # Print all the stats we have collected so far.
38 keys = stats.keys()
39 if len(keys) 0:
40 total = 0.0
41 print %-15s %5s % ('USERNAME', 'MEM%')
42 for k in stats.keys():
43 print %-15s %5.2f % (k, stats[k])
44 total += stats[k]
45 # Finally print a grand total of all users.
46 print %-15s %5.2f % ('TOTAL', total)
It's not the shortest Python script one could write to do what you
describe, but I've gone for readability rather than speed or
conciseness.
Running this script should produce:
$ ./foo.py
USERNAME MEM%
_pflogd 0.10
daemon 0.00
bind 1.10
_dhcp0.10
keramida38.60
smmsp0.10
root10.10
build0.00
TOTAL 50.10
$
PS: Yes, you could probably do the same in bash, with sed, awk and a bit
of superglue, but I prefer Perl and/or Python for anything which
involves something a bit more involved than simple string substitution
these days...
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to [EMAIL PROTECTED]