Linux df Command Usage Examples

This post about Linux df command opens series of articles for Linux newbies where you’ll find description and usage examples of major Linux commands like df, top, fsck, mount and so on.


Linux df command can be used to display disk usage statistics for the file systems present on the Linux system. It’s handy tool to know which filesystem is consuming how much memory. Also, if a particular filename is picked up and supplied as argument to df command then it displays the disk usage statistics for the file system on which the file resides. This command can be used by the system administrators to know the disk usage status of various file systems on Linux so that proper clean-up and maintenance of the Linux system can be performed. The df command provides various options through which the output can be customized in a way that is most suited to the user.

In this article, we will discuss the df command through practical examples.


Before jumping on to the examples, lets first take a look on how to use the df command. Here is the syntax information of df command from the man page:

df [OPTION]... [FILE]...

So we see that the df command does not require any mandatory argument. The OPTION and FILE arguments are non-mandatory. While the OPTION argument tells the df command to act in a way as specified by the definition of that OPTION, the FILE argument tells the df command to print disk usage of only that file system on which the FILE resides.

NOTE: for those who are new to this type of syntax information, any argument specified in square brackets [] are non-mandatory.


1. Basic example

Here is how the df command can be used in its most basic form.

# df 
Filesystem     1K-blocks    Used     Available Use% Mounted on 
/dev/sda6       29640780 4320704     23814388  16%     / 
udev             1536756       4     1536752    1%     /dev 
tmpfs             617620     888     616732     1%     /run 
none                5120       0     5120       0%     /run/lock 
none             1544044     156     1543888    1%     /run/shm

In the output above, the disk usage statistics of all the file systems were displayed when the df command was run without any argument.

The first column specifies the file system name, the second column specifies the total memory for a particular file system in units of 1k-blocks where 1k is 1024 bytes. Used and available columns specify the amount of memory that is in use and is free respectively. The use column specifies the used memory in percentage while the final column ‘Mounted on’ specifies the mount point of a file system.

2. Get the disk usage of file system through a file

As already discussed in the introduction, df can display the disk usage information of a file system if any file residing on that file system is supplied as an argument to it.

Here is an example:

# df test 
Filesystem     1K-blocks    Used      Available Use% Mounted on 
/dev/sda6       29640780    4320600   23814492  16%       /

Here is another example:

# df groff.txt 
Filesystem     1K-blocks    Used     Available Use% Mounted on 
/dev/sda6       29640780    4320600  23814492  16%     /

We used two different files (residing on same file system) as argument to df command. The output confirms that the df command displays the disk usage of file system on which a file resides.

3. Display inode information

There exists an option -i through which the output of the df command displays the inode information instead of block usage.

For example:

# df -i
Filesystem      Inodes    IUsed    IFree     IUse% Mounted on
/dev/sda6      1884160    261964   1622196   14%        /
udev           212748     560      212188    1%         /dev
tmpfs          216392     477      215915    1%         /run
none           216392     3        216389    1%         /run/lock
none           216392     8        216384    1%         /run/shm

As we can see in the output above, the inode related information was displayed for each filesystem.

4. Produce a grand total

There exists an option –total through which the output displays an additional row at the end of the output which produces a total for every column.

Here is an example:

# df --total 
Filesystem     1K-blocks    Used    Available Use% Mounted on 
/dev/sda6       29640780 4320720    23814372  16%     / 
udev             1536756       4    1536752   1%      /dev 
tmpfs             617620     892    616728    1%      /run 
none                5120       0    5120      0%      /run/lock 
none             1544044     156    1543888   1%      /run/shm 
total           33344320 4321772    27516860  14%

So we see that the output contains an extra row towards the end of the output and displays total for each column.

5. Produce output in human readable format

There exists an option -h through which the output of df command can be produced in a human readable format.

Here is an example:

# df -h 
Filesystem      Size  Used   Avail Use% Mounted on 
/dev/sda6       29G   4.2G   23G   16%     /  
udev            1.5G  4.0K   1.5G   1%     /dev 
tmpfs           604M  892K   603M   1%     /run 
none            5.0M     0   5.0M   0%     /run/lock 
none            1.5G  156K   1.5G   1%     /run/shm

So we can see that the output displays the figures in form of ‘G’ (gigabytes), ‘M’ (megabytes) and ‘K’ (kilobytes). This makes the output easy to read and comprehend and thus makes is human readable. Note that the name of the second column is also changed to ‘size’ in order to make it human readable.

Related Links

Manual for df
Index of Linux commands

Track file changes using auditd

Most of Linux distributions comes with Linux Auditing System that makes it possible to track file changes, file accesses as well as system calls. It’s pretty useful functionality for sysadmins who wish to know who and when accessed and/or changed sensitive files like /etc/passwd, /etc/sudoers or others.

Daemon auditd that usually runs in background and starts after reboot by default logs those events into /var/log/audit.log file (or into other file if different syslog facility is specified). The common usage is to list all files which should be watched and search auditd’s logs from time to time. For example, I prefer to track any file changes into /etc/passwd, reading/writing of /etc/sudoers, executing of /bin/some/binary or just everything (read, write, attributes changes, executing) for my /very/important/file.

In order to configure that you’ll need two commands: auditctl and ausearch. First one is for configuring auditd daemon (e.g. setting a watch on a file), second one is for searching auditd logs (it’s possible to use grep against /var/log/audit.log too but ausearch command makes this task easier).

Install and start Linux Auditing System

If it happened that auditd daemon isn’t installed in your system then you can fix this by one of below commands:

sudo apt-get install audit


sudo yum install audit

The next step is to make sure that auditd is running, if command ps ax | grep [a]udit shows nothing then start auditd using command:

/etc/init.d/auditd start

As soon as auditd daemon is started we can start configuring it for tracking file changes using auditctl command.

Make auditd to log all file changes

auditctl -w /etc/passwd -k passwd-ra -p ra

This command will add a rule for auditd daemon to monitor file /etc/passwd file (see option -w /etc/passwd) for reading or changing the atributes (see option -p ra, where r is for read, a is for attribute). Also this command specifies filter key (-k passwd-ra) that will uniquely identify auditd records in its logs files.

Now let’s test this rule: optput the last 20 lines of /etc/passwd file and then search audit log for corresponding records

tail /etc/passwd

and then

[root@test artemn]# ausearch -k passwd-ra
time->Wed Jul  4 15:17:14 2012
type=CONFIG_CHANGE msg=audit(1341407834.821:207310): auid=500 ses=23783 op="add rule" key="passwd-ra" list=4 res=1
time->Wed Jul  4 15:17:20 2012
type=PATH msg=audit(1341407840.181:207311): item=0 name="/etc/passwd" inode=31982841 dev=09:02 mode=0100644 ouid=0 ogid=0 rdev=00:00
type=CWD msg=audit(1341407840.181:207311):  cwd="/home/artemn"
type=SYSCALL msg=audit(1341407840.181:207311): arch=c000003e syscall=2 success=yes exit=3 a0=7fffecd41817 a1=0 a2=0 a3=7fffecd40b40 items=1 ppid=642502 pid=521288 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=23783 comm="tail" exe="/usr/bin/tail" key="passwd-ra"

As you can see the output of second command shows that auditd has one record for filter key ‘passwd-ra’, it shows that root user (uid=0 gid=0) has read file /etc/passwd using command tail (comm=”tail” exe=”/usr/bin/tail”) at July 4, 2012 (time->Wed Jul 4 15:17:20 2012).

Utility ausearch is pretty powerful so I recommend to read output of man ausearch, in the meantime here are some useful examples:

ausearch -x /bin/grep
ausearch -x rm

This approach allows to scan auditd records for certain executable, e.g. if you’d like to see if any of watched files was deleted (or not) using command rm then you should use second command of above two.

This one will show you all records for certain UID (username).

ausearch -ui 1000

Limit CPU usage of Linux process

cpulimit is a small program written in C that allows to limit CPU usage by Linux process. Limit is specified in percentage so it’s possible to prevent high CPU load generated by scripts, programs or processes.

I found cpulimit pretty useful for the scripts running from cron, for example I can do overnight backups and be sure that compression of 50GB file via gzip won’t eat all CPU resources and all other system processes will have enough CPU time.

In most of Linux distributions cpulimit is available from binary repositories so you can install it using commands:

sudo apt-get install cpulimit


sudo yum install cpulimit

If it’s not possible in your distro then it’s extremely easy to compile it:

cd /usr/src/
wget --no-check-certificate -O cpulimit.tar
tar -xvf cpulimit.tar
cd opsengine-cpulimit-9df7758
ln -s cpulimit /usr/sbin/cpulimit

From that moment you can run commands limited by CPU percentage, e.g. below command executes gzip compression so that gzip process will never step over 10% of CPU limit:

/usr/sbin/cpulimit --limit=10 /bin/gzip vzdump-openvz-102-2012_06_26-19_01_11.tar

You can check actual CPU usage by gzip using commands:

ps axu | grep [g]zip



Btw, the first command contains ‘grep [g]zip’ to avoid the last line in common output:

root    896448  10.0  3.1 159524  3528 ?        S    13:12   0:00 /usr/sbin/cpulimit --limit=10 /bin/gzip vzdump-openvz-102-2012_06_26-19_01_11.tar
root       26490  0.0  0.0   6364   708 pts/0    S+   15:24   0:00 grep gzip

Using cpulimit you can also allocate CPU limit to already running processes, e.g. below command will allocate 20% CPU limit to process with PID 2342:

/usr/sbin/cpulimit -p 2342 -l 20

It’s possible to specify process by its executable file instead of PID:

/usr/sbin/cpulimit -P /usr/sbin/nginx -l 30

Performing Oracle RMAN Cold backup

Cold backup is done when database is not open. While performing cold backup using RMAN the database need to be in MOUNT mode. This is because RMAN needs the data file details which are available while database is in MOUNT mode.

Cold backup is also called consistent backup. This is because before bringing the database in MOUNT mode, the database is first shutdown with IMMEDIATE or TRANSACTIONAL option. This means that database sequence number are all synchronised.

Below are the steps to do RMAN cold backup to an external drive in Linux.

Step1: Mount the external drive
Step2: Run in nohup.

The content of is below:

# Set Oracle Environment for DB
#. ~/.bashrc
. ~/.bash_profile

echo “`date` – Started `basename $0`”

rman target /
run {
shutdown immediate;
startup mount;
allocate channel prmy1 type disk format ‘/media/full_backup_%d_%s_%p’;
allocate channel prmy2 type disk format ‘/media/full_backup_%d_%s_%p’;
allocate channel prmy3 type disk format ‘/media/full_backup_%d_%s_%p’;
allocate channel prmy4 type disk format ‘/media/full_backup_%d_%s_%p’;
BACKUP CURRENT CONTROLFILE format ‘/media/ctrl_file_%d_%s_%p’;
release channel prmy1;
release channel prmy2;
release channel prmy3;
release channel prmy4;
alter database open;
if [ $? -eq 0 ]
echo “=====================”
echo “RMAN Backup Completed”
echo “=====================”
echo “==================”
echo “RMAN Backup Failed”
echo “==================”
exit 1

echo “`date` – Finished `basename $0`”

As this backup is a cold backup the, the archive log files will be not required to restore and recover the database. Hence archive log files are not added.

However if you wish to take backup of arrive logs as well you can change




In the above script.

Remember to run the script in nohup.
Also remember to check there is enough space in the external drive.

Linux Restricted Shells: rssh and scponly

Restricted shells like rssh and scponly give sysadmin the possibility to limit the operations that Linux user can do, for example you can create user that will be allowed to copy files via scp but won’t be permitted to login into system’s command line. This is quite important security feature that should be considered by every sysadmin to prevent unauthorized activity by users for example over SSH.

If you have some online storage that is used for uploading backup data over scp or rsync/ssh from remote hosts then it is highly recommended to use restricted shells for those incoming connections and make sure that even if the attacker has got username/password (or key) then he (or she!) won’t be able to break into your system.

scponly is extremely simple restricted shell, user account that has scponly binary as its shell won’t be able to do anything except transfer data from remote host via scp protocol or via rsync/scp. rssh provides little bit more features: you can limit users to use selected protocols like scp, sftp, rsync, cvs or rdist either in chroot environment or not.


I prefer using yum or aptitude to install such kind of software like rssh or scponly so the fastest way is to try one of below commands depending on your needs:

apt-get install rssh
apt-get install scponly
yum install rssh
yum install scponly

If there are problems to find desired restricted shell in your Linux distro’s repository then you should download sources and do some ./configure, make and make install. Here are the links: latest rssh .tar.gz, latest scponly .tgz.


scponly doesn’t need any configuration and works out of the box so you just should set it as a shell for user account. Here are some examples.

Create new user account with scponly as shell:

useradd -s /usr/sbin/scponly user1

Modify user account to set rssh as a shell:

usermod -s /usr/sbin/rssh user2

Where /usr/sbin/scponly is binary executable of scponly.

rssh comes with text configuration file usually stored in /etc/rssh.conf. You can either setup per-user settings there or configure global restrictions for all accounts which are using rssh. Default rssh.conf file is well commented so there shouldn’t be any problems to configure rssh as you needs. At the same time, here are some examples.

If you wish to restrict all users to scp and rsync only then you should uncomment lines in rssh.conf like below:


Now coming to per-user examples. User peter is allowed to use scp protocol only, the following line in rssh.conf will do that:


User ann is allowed to scp, rsync only:


As you can see enabled protocols in per-user setup are specified as 11000 (scp, sftp), 11111 (scp, sftp, cvs, rdist, rsync) or 00000 (no protocols enabled). 022 in above examples specifies umask.


Let’s assume you’ve created user1 and enabled only scp and rsync using rssh. An attempt to access the server via SSH under user1 account will end with the following output:

artiomix$ ssh user1@
user1@'s password: 
This account is restricted by rssh.
Allowed commands: scp rsync
If you believe this is in error, please contact your system administrator.
Connection to closed.

At the same time scp transfers will work without problems:

artiomix$ scp -P 23451 /etc/test.file user1@
user1@'s password:
test.file                             100%  983     1.0KB/s   00:00

Further Reading

rssh support chroot environments for scp, rsync and other transfer protocols. It means that you can restrict users not only by command they can use but also by filesystems they reach. For example, user1 can be chrooted to /chroot_user1 so it can’t be used to copy something from /etc or /var/www directories of the server. Here is nice manual about chroot in rssh.