0

I have a problem that I can't solve, so I've come to you.

I need to write a program that will read all processes and a program must sort them by users and for each user it must display how much of a memory is used.

For example:

user1: 120MB
user2: 300MB
user3: 50MB
total: 470MB

I was thinking to do this with ps aux command and then get out pid and user with awk command. Then with pmap I just need to get total memory usage of a process.

MrLore
  • 3,759
  • 2
  • 28
  • 36
golobitch
  • 1,466
  • 3
  • 19
  • 38

4 Answers4

1

Try this script, which may solve your problem:

#!/bin/bash
function mem_per_user {
    # take username as only parameter
    local user=$1
    # get all pid's of a specific user
    # you may elaborate the if statement in awk obey your own rules
    pids=`ps aux | awk -v username=$user '{if ($1 == username) {print $2}}'`

    local totalmem=0
    for pid in $pids
    do
        mem=`pmap $pid | tail -1 | \
            awk '{pos = match($2, /([0-9]*)K/, mem); if (pos > 0) print mem[1]}'`
        # when variable properly set
        if [ ! -z $mem ]
        then
            totalmem=$(( totalmem + $mem))
        fi
    done

    echo $totalmem
}

total_mem=0
for i in `seq 1 $#`
do
    per_user_memory=0
    eval username=\$$i
    per_user_memory=$(mem_per_user $username)
    total_mem=$(( $total_mem + $per_user_memory))

    echo "$username: $per_user_memory KB"
done
echo "Total: $total_mem KB"

Best regards!

Summer_More_More_Tea
  • 12,740
  • 12
  • 51
  • 83
  • Summer_More_More_Tea, thank you for this code, but when I try to run this in terminal as ./memory.sh, then the above script just display: total: 0KB. Any advice what did I do wrong? – golobitch May 24 '12 at 12:43
  • You're welcomed. Have you specified usernames? This script takes all usernames as arguments delimited by space(` `). For example, you want to check all the memory used by user `summer_more_more_tea` and `root`, the command is `./memory.sh summer_more_more_tea root`. Hope that helps.:) – Summer_More_More_Tea May 24 '12 at 13:00
  • Summer_More_More_Tea, I didn't gave username as argument. But I will try! Thank you very much for your help! ;) But can you modified the script so I don't need to gave usernames as argument? cat /etc/passwd | cut -d: -f1 --> this display all users, so I think this would help. And then for each user script must display memory usage as you write in that script. Because it is crucial to run the script as ./memory.sh , without any arguments And one more thing, what does seq 1 $# means? Regards! – golobitch May 24 '12 at 15:19
  • 1
    @golobich Sorry for my late response. I have see @Tim 's modification and I think it works. Besides `cat`ting `/etc/passwd`, you can `w`, `who`, or `users` to get information about login users(just FYI). – Summer_More_More_Tea May 25 '12 at 04:45
1

it's just a little update, users are automatically selected

#!/bin/bash
function mem_per_user {
    # take username as only parameter
    local user=$1
    # get all pid's of a specific user
    # you may elaborate the if statement in awk obey your own rules
    pids=`ps aux | awk -v username=$user '{if ($1 == username) {print $2}}'`

    local totalmem=0
    for pid in $pids
    do
        mem=`pmap $pid | tail -1 | \
            awk '{pos = match($2, /([0-9]*)K/, mem); if (pos > 0) print mem[1]}'`
        # when variable properly set
        if [ ! -z $mem ]
        then
            totalmem=$(( totalmem + $mem))
        fi
    done

    echo $totalmem
}

total_mem=0
for username in `ps aux | awk '{ print $1 }' | tail -n +2 | sort | uniq`
do
    per_user_memory=0
    per_user_memory=$(mem_per_user $username)
    if [ "$per_user_memory" -gt 0 ]
    then
       total_mem=$(( $total_mem + $per_user_memory))

       echo "$username: $per_user_memory KB"
    fi
done
echo "Total: $total_mem KB"
  • As I see from the code this must be it. But there is one problem: awk: line 1: syntax error at or near , this is displayed several times, so it is probably mistake in the awk in the loop (in function) ? Can you please fix this? Thank you very much! Regards – golobitch May 24 '12 at 20:42
0

You can access the shell commands in python using the subprocess module. It allows you to spawn subprocesses and connect to the out/in/error. You can execute the ps -aux command and parse the output in python.

check out the docs here

nsfyn55
  • 14,875
  • 8
  • 50
  • 77
  • I don'have permissions to use pythone or any other language. Just bash. It must be all writen in bash. Ou and one more think. It must have .sh extension. This won't be a problem. But I am still looking to solution for previous question. Thanks – golobitch May 24 '12 at 02:26
0

Here is my version. I think that Tim's version is not working correctly, the values in KB are too large. I think the RSS column from pmap -x command should be used to give more accurate value. But do note that you can't always get correct values because processes can share memmory. Read this A way to determine a process's "real" memory usage, i.e. private dirty RSS?

#!/bin/bash
 if [ "$(id -u)" != "0" ]; then
 echo "WARNING: you have to run as root if you want to see all users"
 fi
echo "Printing only users that current memmory usage > 0 Kilobytes "
all=0
for username in `ps aux | awk '{ print $1 }' | tail -n +2 | sort | uniq`
do
 pids=`ps aux | grep $username | awk -F" " '{print $2}'`
 total_memory=0
 for pid in $pids
 do
  process_mem=`pmap -x $pid | tail -1 | awk -F" " '{print $4}'`

  if [ ! -z $process_mem ] 
  then #don't try to add if string has no length
   total_memory=$((total_memory+$process_mem))
  fi
 done
#print only those that use any memmory
if [ $total_memory -gt 0 ]
then
 total_memory=$((total_memory/(1024)))
 echo "$username : $total_memory MB"
 all=$((all+$total_memory))
 fi
done
echo "----------------------------------------"
echo "Total: $all MB"
echo "WARNING: Use at your own risk"
Community
  • 1
  • 1
Simon Polak
  • 1,959
  • 1
  • 13
  • 21