12

I need to find out how much disk space is being occupied by each user on the network. I am aware of df and du commands: I could list the entire filesystem and AWK the output, but I wonder if there is a more standard command.

The output I am looking for is:

usr1  xMb
usr2  yMb
[...]
Total zMb

Any ideas?

Thanks!

PS. Red Hat Linux EE

Escualo
  • 221
  • 1
  • 2
  • 4

8 Answers8

11

Is this a one time thing, or is this information you want to be able to extract regularly? In case it is the later then one option is to apply quotas on your filesystem. Doing that the system continuously keeps track of the amount of data used by each user. That way the information is merely a query to the quota database away.

andol
  • 6,848
  • 28
  • 43
  • 1
    +1 quota is the solution! – ThorstenS Dec 15 '09 at 19:48
  • 1
    A one-time thing; possibly a solution which can be stored in a small script for the users to compute their usage if they want to. We cannot limit the amount of data because of the type of work we do does not accommodate hard limits. – Escualo Dec 15 '09 at 19:49
  • @ThorstenS: We do technical computing and we need to generate tons of information which may or may not be removed after a run is made. I don't think quotas help in our situation. – Escualo Dec 15 '09 at 19:50
  • 1
    @Arrieta: You don't have to limit their usage. Simply give each user a ridiculously hight quota. Also, every user can by themselves query the quota database and see how much data they are currently storing. – andol Dec 15 '09 at 20:00
  • 2
    You don't even need to set the quota to a big number, if you leave it unset (i.e. 0) it will not enforce it, but it will record the usage – Daniel Dec 15 '09 at 21:36
  • +1 for using quota as a permament solution. Find and awk are the answer if you only need to ask it once or if you have to answer this during a technical job interview. (I was asked, quota was disabled on that system). – Hennes Aug 22 '14 at 18:39
6

Here is a simple and quick solution that I believe meets your requirement.

I assume that all your users have accounts in the /home directory. All you need to do is to change directory to the /home directory, and then do a du at a depth of 1.

cd /home
sudo du -d 1 -h

Your output will look something like this:

kcyow@linux-server:/home$ sudo du -d 1 -h
7.8M    ./user932
52G     ./user575
20K     ./user329
98G     ./user323
48G     ./user210
148G    ./user44
12M     ./kcyow
362G    ./user28
24G     ./user774
6.2M    ./user143
730G    .
4

Another nice solution I found here. Navigate to the directory of interest, and run (alternatively, change . to whichever directory interests you, e.g., /home/):

find . -type f -printf "%u  %s\n" \
  | awk '{user[$1]+=$2}; END{for(i in user) print i,user[i]}'
Jonas
  • 141
  • 5
4

Or for finding the problem users (directories too),

du -xk | sort -n | tail -25

and for Solaris:

du -dk | sort -n | tail -25   

This gives you a list of the 25 largest directories. Not quite what you asked for, but I use it all the time.

Ben Pilbrow
  • 11,995
  • 5
  • 35
  • 57
Ronald Pottol
  • 1,683
  • 1
  • 11
  • 19
2

What we do in many places is use the quota system, but set absurdly high quotas. This way you get the benefit of fast reporting. At one site, each user has 1 TB of "quota" space.

We periodically bump the quota higher as serviceable disk grows -- initially it was 30GB per user, something that was absurdly high at the time.

David Mackintosh
  • 14,223
  • 6
  • 46
  • 77
0

There ist no such command. You have to write some shell commands for this.

  1. get all users from /etc/passwd with uid >1000
  2. use find -uid and search all files of the user
  3. use this list to feed du -s
ThorstenS
  • 3,084
  • 18
  • 21
  • Inefficient. You do not need to run find several times if you log the information in the same time. Save that information during your first run. Either in a file, or in an associative array. – Hennes Aug 22 '14 at 18:35
0

ThorstenS's method seems like more work then is needed to me because it runs find multiple times. For a one off, I would just do 1 find command, and output the owner and size of each file, and then do some sort magic on that file.

The find would be something like which returns username (or id number of no username) and space used in bytes, in a null-byte delimited file:

sudo bash -c 'find . -printf "%u\0%s\0" > username_usage'

You can replace the \0 with something that might be a little bit easier to work with, like tabs or newlines, but that would be less safe if you have funky file names.

If you wanted to be even more efficient, you could pipe the output to script that handles it as it runs, but that would be a little more work, and you would have to get it right the first time.

Kyle Brandt
  • 82,107
  • 71
  • 302
  • 444
0

I've made it :) Not fast thou, but works:

#!/bin/bash

# Displays disk usage per user in the specified directory
# Usage: ./scriptname [target-directory]

[ "x$1" == "x" ] && dirname="." || dirname="$1"
for uid in `cat /etc/passwd |awk -F : '{ print $1 }' ` ; do # List all usernames
    user_size=0
    for file in `find "$dirname" -type f -user "$uid" 2>/dev/null` ; do # List the folder's files that belongs to the current user, Ignore possible `find` errors.
        let user_size+=`stat -c '%s' $file` # Sum-up
        done
    [ $user_size -gt 0 ] && echo "USER=$uid, SIZE=$user_size" # Display the result if >0
    done

Great speed increase will occur if we seek only for UIDs that are >1000:

- for uid in `cat /etc/passwd | sed -rn "s~^([^:]+):.*$~\1~p"` ; do # List all usernames
+ for uid in `cat /etc/passwd | sed -rn "s~^([^:]+):[^:]:[0-9]{4,}:.*$~\1~p"` ; do # List all usernames having UID>1000
kolypto
  • 10,738
  • 12
  • 51
  • 66