Find the Processes Writing Too Much with iotop

iotop-py shows which process is hammering your disk, but only if you know which of its many flags stop it running forever. By the end of this guide you will be able to run it, identify the processes generating disk traffic, and collect a small, script-friendly sample. Allow about ten minutes. You need the installed iotop package, a terminal, and usually sudo access.

Before you start

This guide was checked against iotop 0.6, packaged locally as iotop 0.6-42-ga14256a-0.2build1. The command installed by that package is /usr/sbin/iotop-py; iotop is the documented alias.

The program reads accounting data from the Linux kernel. Its manpage says the kernel needs task delay accounting, task I/O accounting, task statistics and VM event counters. Since Linux 5.14, kernel.task_delay_acct must also be enabled. These are kernel prerequisites, not switches that iotop can repair for you.

There is a second boundary: the installed program refuses an ordinary unprivileged run when it cannot access the required interfaces. It reports that root privileges or the NET_ADMIN capability are needed. Start with the harmless version and help checks:

$ iotop-py --version
iotop 0.6
$ iotop-py --help
Usage: /usr/sbin/iotop-py [OPTIONS]

Checkpoint: If --version works, you have found the expected executable. If the command is missing, stop and install the package through your normal system administration process. Do not copy a random script into /usr/sbin.

1. Run the interactive view

Run this command with elevated privileges:

$ sudo iotop-py

The display normally includes read and write bandwidth, swap-in percentage, time waiting on I/O, and the I/O priority for each process or thread. It also shows totals near the top. Those totals are not guaranteed to match the current disk figures: caching and I/O reordering mean that process-to-kernel traffic and kernel-to-device traffic can differ at a moment in time.

The default view includes threads. That can make a busy service look like many separate offenders. Press p to toggle process-only output. Press the left and right arrow keys to choose the sorting column, r to reverse its order, and o to show only entries that are doing I/O. Press q to leave.

Checkpoint: After pressing o, idle entries should disappear. If the list is still long, press p and sort by a disk column. Treat a short burst as a clue, not proof of a sustained workload.

2. Narrow the question

To watch one process or thread, replace PID with a real numeric identifier:

$ sudo iotop-py --pid PID

To watch one user, replace USER with an account name or the value accepted by your local installation:

$ sudo iotop-py --user USER

The --pid and --user options are filters. They do not change the process, its priority, or any files. Confirm the identifier first with a read-only command such as ps -p PID -o pid,user,comm,args.

Do not confuse observation with the interactive i key. That key changes the I/O priority of a process or its threads. Changing priority is an operational action and can alter workload behaviour. Avoid it unless you have a specific reason and know how to restore the previous priority with ionice.

3. Capture a bounded sample

Interactive output is useful for a live incident, but a bounded batch run is easier to save or compare. This example takes five samples, one second apart, shows only active processes, adds timestamps, and uses kilobytes for stable columns:

$ sudo iotop-py --batch --iter=5 --delay=1 --only --processes --kilobytes --time

--iter=5 matters because iotop runs indefinitely by default. --delay=1 is the default interval, but stating it makes the sample reproducible. --time implies batch mode. The output contains timestamped rows and numeric kilobyte values; the exact processes and figures depend on the machine at that moment.

For a compact log, add quiet options. One -q removes some header lines, and the option may be repeated up to three times. At -qq, column names are not repeated; at -qqq, the I/O summary is also suppressed:

$ sudo iotop-py -b -n 5 -d 1 -o -P -k -t -qq

Use a shell redirection only when you have chosen the destination deliberately. The command below creates or replaces the named file, so check the path before pressing Enter:

$ sudo iotop-py -b -n 5 -d 1 -o -P -k -t -qq > /tmp/iotop-sample.txt
$ sed -n '1,12p' /tmp/iotop-sample.txt

Warning: The redirection overwrites an existing /tmp/iotop-sample.txt. Choose another path if that file contains evidence you still need. When finished, remove this temporary sample with rm -- /tmp/iotop-sample.txt if it contains no information you need to retain.

4. Read the result without overclaiming

Bandwidth columns describe the sampling period. The -a or --accumulated option changes the question: it shows the amount of I/O performed since iotop started rather than a current rate. That is useful for finding a process that has done a lot of work over the lifetime of the monitor, but it is not a replacement for a rate sample.

Total disk read and write values describe traffic between processes or kernel threads and the block-device subsystem. Current disk read and write values describe traffic between that subsystem and the underlying hardware. Caches and reordering explain why the two pairs may differ. If you need a device-level view, corroborate the observation with another tool such as vmstat rather than treating one iotop row as a complete storage diagnosis.

Common failures

Done means