29

Let's say i have 20 users logged on my linux box. How can I know how much memory each of them is using?

13 Answers 13

24

You could try using smem (see ELC2009: Visualizing memory usage with smem for more information). In particular, sudo smem -u should give you the information you want.

5
  • 1
    I agree this is probably the best way to this. However, smem needs a really modern kernel, which none of the established enterprise distros deliver. So unless you are running a community distro like Fedora, OpenSUSE or a non-LTS Ubuntu, you're out of luck.
    – wzzrd
    Jun 24, 2009 at 15:29
  • This is great. Thanks alot. I didn't know about the smem. It looks like it will do the job. Jun 24, 2009 at 22:26
  • 4
    FYI, smem requires a kernel >= 2.6.27
    – xebeche
    Sep 10, 2010 at 17:14
  • smem also requires a bunch of stuff like gtk here, not an option.
    – anarcat
    Oct 28, 2014 at 19:18
  • @anarcat: Not true (at least for Debian jessie). The only dependency is python, python-matplotlib is only a recommended package that you can skip with --no-install-recommends.
    – Léo Lam
    Apr 11, 2016 at 19:23
14

Ignoring shared memory issues, here's a quick script that gives you RSS and VMEM for all logged in users, sorted by vmem, and organized into cute columns:

(echo "user rss(KiB) vmem(KiB)";
 for user in $(users | tr ' ' '\n' | sort -u); do
   echo $user $(ps -U $user --no-headers -o rss,vsz \
     | awk '{rss+=$1; vmem+=$2} END{print rss" "vmem}')
 done | sort -k3
) | column -t

This version prints memory usage in GB and sorts by RSS:

echo "user       rss(GB) vmem(GB)";
for user in $(users | tr ' ' '\n' | sort -u); do
    ps -U $user --no-headers -o rss,vsz \
        | awk -v user=$user '{rss+=$1; vmem+=$2} END{printf("%-10s %7.1f %8.1f\n", user, rss/1024/1024, vmem/1024/1024)}'
done | sort --general-numeric-sort --key=2 --reverse
3
  • Well, sadly 'ignoring shared memory issues' this script also outputs complete bogus.
    – fgysin
    Nov 19, 2014 at 15:22
  • 2
    bogus? bogus what? how is the output bogus exactly?
    – anarcat
    Mar 20, 2015 at 19:51
  • o/p is in rss and vmem, what is rss & vmem?
    – vidur punj
    Mar 13, 2018 at 10:33
6

To get sum of RSS I think the following works. This would be to get the sum of RSS for the users kbrandt and root.

ps -U kbrandt,root --no-headers  -o rss | (tr '\n' +; echo 0) | bc
1
6

Looking for the same, I figured out this

ps aux | awk '{arr[$1]+=$4}; END {for (i in arr) {print i,arr[i]}}' | sort -k2

to print processes ordered by mem, grouped by user (column1, the $1), you can group by other things, and sum other things, changing $1 and $4

  • $1 is the first column: user name (groups by this)
  • $4 is the fourth column: %mem (sums this)

I was happy to find the solution, just wanted to share.

2
  • 1
    Thanks! I made a few modifications and am using this: ps --no-headers -eo user,rss | awk '{arr[$1]+=$2}; END {for (i in arr) {print i,arr[i]}}' | sort -nk2. The sort command needs the -n flag to make it parse the memory as a number. Also this way you can replace the word "user" with "command" to group by application name instead.
    – Tim
    Dec 28, 2015 at 15:23
  • Actually that should be $NF instead of $2 in my comment above to get the last column from awk (as $2 doesn't work with commands that have spaces in them). Seems I can't edit the comment any more.
    – Tim
    Dec 28, 2015 at 15:57
4

That's a tricky question. You could easily sum up the total RSS+swap amounts in "ps" output, but what about shared memory? Different users could easily share the same code page if they're running the same process. Who do you account that to? What about buffers and cache? It really depends on how accurate you want your results to be. The more accurate you want, the harder it will be.

2
  • I think your right PS is the answer, but you probably need to ignore shared memory.
    – Jason Tan
    Jun 24, 2009 at 14:26
  • smem (mentioned in my answer) solves the shared memory problem with its PSS and USS measurements (PSS proportionally distributes the shared memory between the processes which share it).
    – CesarB
    Jun 24, 2009 at 15:06
2

I'm not sure how to report memory usage by user but if you're concerned about controlling their usage then you should look up ulimit. It will allow you to set hard and soft limits on a per user/group basis for memory and other resources on your system.

2

You may try something like:

ps auxU maxwell | awk '{memory +=$4}; END {print memory }'

2
  • Thanks! For the current user this could be also done e.g. with ps -o user,rss --no-headers | awk '{mem+=$2}; END{print mem}'
    – xebeche
    Sep 10, 2010 at 17:27
  • I edited this slightly as ps aux | grep mysql | awk '{memory +=$4}; END {print memory }', where mysql could be replaced with the name of a user or process.
    – jeshurun
    Oct 31, 2017 at 6:18
2

This bash script is probably ugly as hell, but thank you for the exercise, my bash was (is) getting rusty!

#!/bin/sh
OLDIFS=$IFS
IFS=$'\n'
tempsum=0
totalmem=0
for m in `ps -eo user,rss --sort user | sed -e 's/  */ /g' | awk -F'[ ]' {'print $0'}`; do
  nu=`echo $m|cut -d" " -f1`
  nm=`echo $m|cut -d" " -f2`
  # echo "$nu $nm $nu"
  if [ "$nu" != "$ou" ] && [ $(echo "$nm"|grep -E "^[0-9]+$") ] 
  then 
    if [ "$tempsum" -ne 0 ]; then echo "Printing total mem for $ou: $tempsum"; fi
    ou=$nu
    tempsum=$nm
    let "totalmem += $nm"
  else 
    let "tempsum += $nm" 
    let "totalmem += $nm"
  fi
done
echo "Total Memory in Use: $totalmem/$(free | grep Mem: | awk '{print $2}')"
IFS=$OLDIFS

Result:

[20:34][root@server2:~]$ ./memorybyuser.sh 
Printing total mem for admin: 1387288
Printing total mem for apache: 227792
Printing total mem for avahi: 1788
Printing total mem for dbus: 980
Printing total mem for 68: 3892
Printing total mem for root: 55880
Printing total mem for rpc: 292
Printing total mem for rpcuser: 740
Printing total mem for smmsp: 720
Printing total mem for xfs: 680
Total Memory in Use: 1682360/4152144

Please comment/correct and I will update the answer. Also I use the rss memory output from PS, as others have discussed there are pros/cons to using this value.

2
  • It has a small problem - it will not print the "Printing total mem for $ou: $tempsum" for the last user in the ps output. The loop will just add the last program to the amount used by a user and then it will quit. Jun 24, 2009 at 22:25
  • Wow. Your script was more than helpfull !!!! You can't imagine ! Can I ask for something though if its not too much ? Can you make it show also total cpu usage ? And possibly maybe can it be made to show memory usage if its more than 100mb ?
    – user128563
    Jul 17, 2012 at 7:28
1

smem wasn't available on my system, and Dave's script didn't work for some reason, so I wrote this ugly Perl oneliner to process ps output:

ps -eo user,rss | perl -e 'foreach (<>) { m/(\w+)\s+(\d+)/; $mem{$1} += $2; }; foreach $u (keys %mem) { if ($mem{$u}) { print "$u - $mem{$u}\n" }}' | sort

Note that some users were identified using their UID rather than their username. You could deal with this by parsing usernames from /etc/passwd, using the uglier:

ps -eo user,rss | perl -e 'open(F, "/etc/passwd"); foreach $l (<F>) { if ($l=~/(.*?):.*?:(\d+)/) { $users{$2}=$1; }}; foreach (<>) { m/(\w+)\s+(\d+)/; $mem{$1} += $2; }; foreach $u (keys (%mem)) { $UN = $u; if ($UN=~/^\d+$/) { $UN = $users{$UN};}; if ($mem{$u}) { print "$UN - $mem{$u}\n" }}' | sort
0

Using Bash Script

#!/bin/bash

total_mem=0     

printf "%-10s%-10s\n" User MemUsage'(%)'    

while read u m

do
        [[ $old_user != $u ]] && {  printf "%-10s%-0.1f\n" $old_user $total_mem;

                                    total_mem=0; }

        total_mem="$(echo $m + $total_mem | bc)"    
        old_user=$u

done < <(ps --no-headers -eo user,%mem| sort -k1)    

#EOF

OUTPUT

User      MemUsage(%)
apache    4.8
dbus      0.0
mysql     3.8
nagios    3.1
0
pmap `pgrep -u 503` | grep total | awk '{print $2}' | awk '{s+=$1}END{print s}'

503 - UID

You can get the UIDs from /etc/passwd to do this for all users

0

Well, at this state of Linux kernel I can think of only one proper way to accomplish this task — using memory cgroups. You'd need to put a user on-login into own cgroup, and this might require own pam module development or (rather) modifying existing module for that.

Useful doc to read on this is: Resource Management Guide by RedHat®.

0

This could help you to check memory usage for specific user.

for i in {User1,User2};
do
mem=`ps -U $i --no-headers -o rss | awk '{ sum+=$1} END {print int(sum/1024) "MB"}'`
echo $i, $mem
done

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .