Iotop: Pinpointing Per-Process Storage Saturation, Triaging Thread-Level I/O Spikes, and Profiling Disk Bottlenecks in Production
The harsh chime of your phone pierces the silence at 02:14 on a Tuesday morning. Your on-call alert channel is alight with red banners: the core database cluster has breached its latency thresholds, API gateways are shedding incoming traffic with a cascade of 504 timeouts, and the primary application is entirely frozen. Half-awake and squinting into the glare of a laptop screen, you dial into an emergency incident room where engineers are frantically debating what broke. The server's load average is climbing at a terrifying pace, yet nobody can explain why the machine has ground to a halt.
You open an SSH session through the bastion host and inspect the system state. A baffling contradiction appears. Running uptime confirms catastrophic queueingβa load average well over 80 on a 16-core machine. Yet launching standard top reveals that CPU cores are practically idling, with user and system activity barely touching 12%. Instead, more than 80% of CPU time is trapped in iowait, stalled while threads wait for disk operations to complete. Running vmstat 1 confirms that dozens of vital processes are stuck in uninterruptible sleep state (D-state), queueing behind a choked storage bus.
| Diagnostic Metric | Observed Value | System Impact |
|---|---|---|
| System Load Average | 86.42, 64.18, 22.05 |
Severe task queue saturation across all 16 cores |
| CPU Utilization | 12% user/system |
Compute capacity remains overwhelmingly idle |
Block I/O Wait (%wa) |
82% iowait |
Execution threads suspended waiting for storage hardware |
| Process State | 40+ in D-state |
Critical services blocked in uninterruptible kernel sleep |
Traditional system monitors fail you at this exact juncture. Standard tools track CPU cycles and memory allocations with great precision, but remain entirely blind to the volume of data moving across the storage bus. In the middle of an escalating outage, you need a specialised diagnostic tool that interrogates the Linux kernel's storage accounting subsystem: iotop.
The fastest way to cut through the confusion on a degraded server is to launch iotop filtered exclusively for active disk activity:
sudo iotop -o -d 1
By supplying -o (to hide hundreds of dormant background processes) and -d 1 (to refresh telemetry every second), you strip away the background noise and instantly isolate the offending tasks:
Total DISK READ: 0.00 B/s | Total DISK WRITE: 142.18 M/s
Current DISK READ: 0.00 B/s | Current DISK WRITE: 168.45 M/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
48192 be/4 postgres 0.00 B/s 138.64 M/s 0.00 % 88.12 % postgres: writer process
48194 be/4 postgres 0.00 B/s 3.54 M/s 0.00 % 12.40 % postgres: walwriter process
1024 be/4 root 0.00 B/s 0.00 B/s 0.00 % 2.10 % [kworker/u32:2-flush]
In a single glance, the mystery dissolves: a single database process is flooding the storage controller with nearly 140 megabytes of writes every second, consuming 88% of the available I/O capacity and starving every other process on the host.
What It Does in Plain English
The iotop utility is a real-time monitor for storage subsystem activity on Linux. Where traditional tools such as top or htop tell you which process is consuming CPU or memory, iotop reveals which process is reading from or writing to disk, and how much time each thread spends waiting for physical storage devices to finish processing requests.
Rather than looking only at aggregate disk metrics across physical drive arraysβthe way utilities like iostat doβiotop inspects kernel-level telemetry on a per-process and per-thread basis. It shows you the exact bandwidth consumed by every background job, rogue script, or database worker, alongside the percentage of execution time lost to disk stalls or swap activity. This makes it an indispensable tool for diagnosing mysterious system slowdowns, runaway batch pipelines, and storage bottlenecks.
Core Flags & Operational Modes
The behavior of iotop is controlled through a concise set of command-line flags tailored for interactive debugging, headless forensic logging, and targeted process inspection:
-o(--only): Filters the display to show only processes or threads actively performing disk read or write operations, eliminating idle background tasks.-b(--batch): Enables non-interactive batch mode, disabling the curses-based terminal interface so output can be redirected to log files or parsed by shell scripts.-n NUM(--iter=NUM): Restricts execution to a fixed number of sampling iterations before exiting cleanly.-d SEC(--delay=SEC): Configures the polling interval in seconds between metric refreshes, supporting fractional increments.-P(--processes): Aggregates all constituent lightweight threads into their parent Process IDs (PIDs), providing a process-level rather than thread-level summary.-a(--accumulated): Switches to cumulative accounting mode, displaying total data transferred sinceiotopstarted rather than interval throughput rates.-k(--kilobytes): Enforces a fixed bandwidth reporting unit of kilobytes per second, preventing automatic switching between bytes, megabytes, and gigabytes.-t(--time): Adds an accurate timestamp to each output row, essential for aligning batch logs with system incident timelines.-p PID(--pid=PID): Restricts monitoring to a specific process identifier or list of thread IDs.-u USER(--user=USER): Filters accounting metrics to show only processes owned by a given user account.
Architectural Mechanics: Netlink Taskstats and Kernel Delay Accounting
To understand how iotop surfaces its data, one must look beneath the user space interface into the accounting architecture of the Linux kernel. Rather than repeatedly scraping /proc/[pid]/ioβa naive approach that misses short-lived threads and creates heavy system overheadβiotop communicates directly with the kernel using the Generic Netlink protocol (NETLINK_GENERIC), querying the TASKSTATS interface.
β’ blkio_delay (nanoseconds)
β’ swapin_delay (nanoseconds)"] IOACCT["Task I/O Accounting (CONFIG_TASK_IO_ACCOUNTING)
β’ read_bytes / write_bytes
β’ cancelled_write_bytes
β’ syscr / syscw counters"] end SCHED["Core Scheduler & Process Descriptors (struct task_struct)"] end IOTOP <--> NETLINK NETLINK <--> TASKSTATS TASKSTATS --> DELAY TASKSTATS --> IOACCT DELAY --> SCHED IOACCT --> SCHED
Kernel Prerequisites
For iotop to gather detailed telemetry, the running kernel must be compiled with three core configuration parameters:
CONFIG_TASKSTATS: Enables the infrastructure that exports per-task accounting records to user space via Netlink sockets.CONFIG_TASK_DELAY_ACCT: Enables delay accounting, allowing the kernel to measure the exact nanoseconds tasks spend waiting for block I/O operations or page swapping.CONFIG_TASK_IO_ACCOUNTING: Instruments the storage layer to record actual read and write byte counters within each thread'sstruct task_struct.
When iotop starts a sampling loop, it issues a TASKSTATS_CMD_GET command over its Netlink socket. The kernel responds with a structured struct taskstats payload containing raw nanosecond timers and monotonic byte counters.
Metric Computation Mechanics
The columns displayed by iotop are calculated directly from this kernel payload:
- DISK READ and DISK WRITE: Derived from
read_bytesandwrite_bytes.iotopsamples these cumulative counters across successive time intervals ($\Delta t$), computing throughput as: $$\text{Throughput} = \frac{\text{bytes}{t_2} - \text{bytes}{t_1}}{t_2 - t_1}$$ Note on Page Cache Dynamics: Thewrite_bytesmetric captures data handed off to the kernel page cache by write system calls (sys_write,pwrite64). Physical storage read operations indicate cache-miss block reads that must hit underlying disk controllers directly. - Block I/O Delay (
%IO): Calculated fromblkio_delay_total, a monotonic counter tracking the cumulative nanoseconds a thread spent in uninterruptible sleep waiting for synchronous block operations to finish: $$\%IO = \left( \frac{\Delta \text{blkio_delay_total}}{\Delta t} \right) \times 100$$ - Page Swap-in Delay (
%SWAPIN): Derived fromswapin_delay_total, recording the cumulative time a thread spent suspended while pages of memory were fetched back from disk swap space into physical RAM.
5 Real-World Production Use Cases
| Incident Category | Operational Scenario | Diagnostic Focus |
|---|---|---|
| Write Amplification Contention | Multi-Threaded RDBMS | Isolating rogue queries dominating write bandwidth |
| Post-Incident Forensic Telemetry | Non-Interactive Batch Logging | Capturing transient overnight I/O spikes via headless polling |
| Slow-Leak Storage Consumption | Accumulated Worker Pools | Tracking cumulative lifetime byte churn across background tasks |
| Swap-In Latency vs Block Wait | Memory Pressure Triage | Distinguishing memory paging (%SWAPIN) from disk stall (%IO) |
| Automated SRE Remediation | Dynamic I/O Throttling | Auto-detecting offenders, capturing call stacks, and demoting via ionice |
1. Isolating High-Throughput Rogue Threads During Write Amplification Events
Scenario
A primary PostgreSQL node experiences sudden query latency degradation. While the overall process tree indicates standard database operations, lock contention and write-ahead log (WAL) synchronization have created a write amplification spiral, dragging the storage arrayβs NVMe controller into severe write-queue saturation.
Command
sudo iotop -P -t -o -d 2
Realistic Terminal Output
02:14:01 Total DISK READ: 0.00 B/s | Total DISK WRITE: 489.12 M/s
02:14:01 Current DISK READ: 0.00 B/s | Current DISK WRITE: 512.30 M/s
TIME PID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
02:14:01 89211 be/4 postgres 0.00 B/s 462.10 M/s 0.00 % 94.20 % postgres: 14/main: analytics_user reporting_db [local] COPY
02:14:01 89012 be/4 postgres 0.00 B/s 26.80 M/s 0.00 % 14.15 % postgres: 14/main: checkpointer
02:14:01 89014 be/4 postgres 0.00 B/s 0.22 M/s 0.00 % 1.05 % postgres: 14/main: walwriter
Line-by-Line Technical Analysis
02:14:01 Total DISK READ ... Total DISK WRITE: 489.12 M/s: Shows the aggregate physical block storage ingestion across all processes on the operating system host.PID 89211: Identifies the rogue connection belonging to useranalytics_userexecuting a massive bulk data import (COPY).DISK WRITE 462.10 M/s: Indicates that this single backend thread is responsible for generating over 94% of the machine's total storage writes.IO 94.20 %: Demonstrates that the thread is spending 94.20% of its operational time waiting for synchronous I/O operations (flushes to disk and checkpoint synchronization), starving concurrent OLTP queries.
Operational Remediation
The engineer immediately cancels the rogue backend query via SQL:
SELECT pg_cancel_backend(89211);
If the connection is unresponsive due to kernel D-state stalls, the engineer isolates the PID using ionice to drop its scheduling priority to the idle class:
sudo ionice -c 3 -p 89211
2. Headless Non-Interactive Batch Telemetry for Post-Incident RCA
Scenario
A Kubernetes node hosting microservices periodically suffers transient I/O freezes every night between 03:00 and 04:00 UTC. The anomalies last only 30 to 45 seconds, making real-time interactive diagnosis impossible. The infrastructure team requires headless forensic telemetry logging to disk to capture the root cause during the next incident window.
Command
sudo iotop -b -n 5 -d 2 -o -k -t > /var/log/iotop_incident.log
(Configured via a cron or systemd timer during the target window to collect 5 discrete 2-second samples).
Realistic Terminal Output (Log Extract)
03:17:42 Total DISK READ: 0.00 K/s | Total DISK WRITE: 184512.44 K/s
03:17:42 Current DISK READ: 0.00 K/s | Current DISK WRITE: 201450.12 K/s
TIME TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
03:17:42 34102 be/4 root 0.00 K/s 184200.00 K/s 0.00 % 82.45 % journalctl --vacuum-size=10G
03:17:44 Total DISK READ: 0.00 K/s | Total DISK WRITE: 192410.10 K/s
03:17:44 Current DISK READ: 0.00 K/s | Current DISK WRITE: 198210.00 K/s
TIME TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
03:17:44 34102 be/4 root 0.00 K/s 192100.00 K/s 0.00 % 85.10 % journalctl --vacuum-size=10G
Line-by-Line Technical Analysis
03:17:42 ... 03:17:44: The-tand-bflags create a predictable, structured timeline where each sampling slice provides absolute timestamps alongside exact transfer rates in kilobytes (-k).TID 34102 ... root: Exposes a background administrative maintenance command (journalctl --vacuum-size=10G) initiated by an uncoordinated log rotation script.DISK WRITE 184200.00 K/s ... 192100.00 K/s: The log consolidation utility is rewriting and purging massive index journals at ~185β192 MB/s without I/O scheduling constraints.IO 82.45 %: Confirms the disk subsystem was overwhelmed, causing all collocated container runtimes sharing the root mount to stall.
Operational Remediation
The SRE updates the log rotation systemd service definition to wrap the vacuuming routine in low-priority I/O and CPU scheduling classes:
[Service]
CPUSchedulingPolicy=idle
IOSchedulingClass=idle
IOSchedulingPriority=7
3. Tracking Accumulated Cumulative I/O Consumption Across Long-Running Worker Pools
Scenario
A fleet of Celery worker processes handling asynchronous background tasks is deployed on an application server. Over several days, SSD write-endurance monitoring reports abnormal degradation. The engineering team must identify which specific worker process is silently leaking write operations or executing repetitive, un-cached local disk writes over time.
Command
sudo iotop -b -n 1 -a -P
Realistic Terminal Output
Total DISK READ: 28.45 G | Total DISK WRITE: 894.12 G
Current DISK READ: 0.00 B/s | Current DISK WRITE: 0.00 B/s
PID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
12844 be/4 celery 1.12 G 742.80 G 0.00 % 4.12 % celery worker: queue_media_transcode [worker-3]
12842 be/4 celery 0.85 G 52.10 G 0.00 % 0.45 % celery worker: queue_notifications [worker-1]
12843 be/4 celery 0.90 G 48.30 G 0.00 % 0.41 % celery worker: queue_notifications [worker-2]
1105 be/4 root 0.12 G 12.45 G 0.00 % 0.05 % rsyslogd -n
Line-by-Line Technical Analysis
Total DISK WRITE: 894.12 G: The-aflag switchesiotopinto cumulative accounting mode, presenting total data transferred across the lifetime of the monitored processes rather than instantaneous rates.PID 12844 (queue_media_transcode): Instantly surfaces as the primary consumer, having committed 742.80 GB of disk writes out of the node's total 894.12 GB.DISK READ 1.12 G: Highlights an extreme write-to-read asymmetry (~660:1 ratio), indicative of unbuffered temporary file dumps rather than balanced read/write processing.SWAPIN 0.00 %: Confirms the node is not experiencing memory pressure; the issue is purely application-level storage churn.
Operational Remediation
The development team inspects the media transcoding task implementation and discovers that the worker is spooling raw video frames to /tmp (backed by the physical SSD root volume) instead of utilizing a memory-backed tmpfs mount:
# Create an in-memory mount for intermediate video chunks
sudo mount -t tmpfs -o size=8G tmpfs /mnt/transcode_scratch
The application configuration is updated to route intermediate workspace directories to /mnt/transcode_scratch.
4. Triaging System Responsiveness Degradation: Swap-In Latency (%SWAPIN) vs Physical Block Waiting (%IO)
Scenario
A Kubernetes node hosting memory-intensive JVM microservices becomes unresponsive. SSH sessions lag, metrics collection agents fail heartbeats, and web applications experience intermittent latency spikes. The operations team must determine whether the underlying cause is storage hardware saturation (block queue depth collapse) or memory exhaustion leading to swap thrashing.
Command
sudo iotop -b -n 2 -o
Realistic Terminal Output
Total DISK READ: 112.45 M/s | Total DISK WRITE: 4.12 M/s
Current DISK READ: 120.10 M/s | Current DISK WRITE: 3.80 M/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO COMMAND
55210 be/4 java 58.12 M/s 0.00 B/s 89.45 % 92.10 % java -Xmx16G -jar payment-service.jar
55211 be/4 java 54.33 M/s 0.00 B/s 87.12 % 89.60 % java -Xmx16G -jar payment-service.jar
412 be/4 root 0.00 B/s 4.12 M/s 0.00 % 8.30 % [kswapd0]
Line-by-Line Technical Analysis
TID 55210 & 55211: Worker threads of the primary JVM process (payment-service.jar).DISK READ ~112.45 M/s combined: The process is executing heavy reads from storage, but this is not normal application data access.SWAPIN 89.45 % & 87.12 %: The critical diagnostic indicator. Nearly 90% of the threads' operational lifecycle is halted waiting for memory pages to be read back from the swap partition into physical RAM.IO 92.10 %: Confirms the threads are in deepD-statewaiting for storage controllers, but the root cause is swap starvation, not slow database queries.[kswapd0]: The Linux kernel swap daemon is actively writing dirty pages out to storage at 4.12 MB/s to reclaim anonymous pages.
Operational Remediation
The engineer recognizes that the host has overcommitted its physical memory, triggering a swap storm. Immediate mitigation requires lowering kernel swappiness and adjusting container memory limits:
# Verify current system swappiness
sysctl vm.swappiness
# Lower kernel inclination to swap anonymous memory (runtime temporary fix)
sudo sysctl vm.swappiness=10
The JVM heap limits are properly capped in the Kubernetes deployment manifest (resources.limits.memory configured with adequate overhead above -Xmx16G).
5. Building an Automated SRE Remediation Daemon with Dynamic ionice Throttling and Stack Capture
Scenario
In a shared multi-tenant environment, un-curated customer scripts or automated batch jobs periodically hijack the storage subsystem, breaching baseline service level indicators (SLIs) for neighboring tenants. The infrastructure architecture mandates an automated remediation daemon that continuously analyzes headless batch iotop output, automatically detects PIDs breaching write bandwidth thresholds, drops their I/O priority using ionice, and dumps their kernel stack traces for offline forensics.
SRE Remediation Script: io_throttle_sentinel.sh
#!/usr/bin/env bash
# ==============================================================================
# io_throttle_sentinel.sh - Automated Kernel I/O Enforcer and Forensic Collector
# ==============================================================================
set -euo pipefail
WRITE_THRESHOLD_KB=50000 # 50 MB/s threshold
LOG_FILE="/var/log/io_throttle_sentinel.log"
FORENSIC_DIR="/var/log/io_forensics"
mkdir -p "${FORENSIC_DIR}"
log_msg() {
echo "[$(date -u +'%Y-%m-%dT%H:%M:%SZ')] $1" | tee -a "${LOG_FILE}"
}
log_msg "Initializing I/O Sentinel Daemon..."
# Execute iotop in batch mode with 1-second interval, KB formatting, showing only active processes
sudo iotop -b -d 1 -n 1 -o -k -P | tail -n +3 | while read -r line; do
# Extract columns from iotop output: PID, PRIO, USER, DISK READ, DISK WRITE, SWAPIN, IO, COMMAND
PID=$(echo "${line}" | awk '{print $1}')
DISK_WRITE_KB=$(echo "${line}" | awk '{print $5}' | cut -d'.' -f1)
COMMAND=$(echo "${line}" | awk '{for(i=8;i<=NF;++i) printf "%s ", $i; print ""}')
# Validate integer formatting
if [[ "${DISK_WRITE_KB}" =~ ^[0-9]+$ ]]; then
if [ "${DISK_WRITE_KB}" -gt "${WRITE_THRESHOLD_KB}" ]; then
log_msg "VIOLATION DETECTED: PID ${PID} (${COMMAND}) generating ${DISK_WRITE_KB} KB/s write throughput."
# Forensic Collection: Dump kernel execution stack
if [ -f "/proc/${PID}/stack" ]; then
FORENSIC_FILE="${FORENSIC_DIR}/stack_${PID}_$(date +%s).log"
cat "/proc/${PID}/stack" > "${FORENSIC_FILE}" 2>/dev/null || true
log_msg "Forensic kernel call-stack persisted to ${FORENSIC_FILE}"
fi
# Remediation: Demote task to Idle I/O Scheduling Class (Class 3)
if command -v ionice >/dev/null 2>&1; then
ionice -c 3 -p "${PID}"
log_msg "Remediation Applied: Demoted PID ${PID} to ionice Class 3 (IDLE)."
fi
fi
fi
done
Demonstration Execution Output
[2026-08-19T00:14:02Z] Initializing I/O Sentinel Daemon...
[2026-08-19T00:14:03Z] VIOLATION DETECTED: PID 67210 (dd if=/dev/zero of=/var/tmp/corrupt.img bs=1M ) generating 184512 KB/s write throughput.
[2026-08-19T00:14:03Z] Forensic kernel call-stack persisted to /var/log/io_forensics/stack_67210_1755562443.log
[2026-08-19T00:14:03Z] Remediation Applied: Demoted PID 67210 to ionice Class 3 (IDLE).
Operational Next Steps
- Inspect the generated stack trace (
/var/log/io_forensics/stack_67210_*.log) to pinpoint the specific system calls (vfs_write,ext4_file_write_iter, orxfs_file_buffered_aio_write) invoked by the offending binary. - Enforce hard I/O isolation boundaries at the container level by configuring
systemdor cgroup v2 limits via theio.maxcontroller (e.g.,rbps=,wbps=,riops=,wiops=).
What Can Go Wrong: Operational Hazards, Security Capabilities, and Overhead
| Operational Hazard | Underlying Root Cause | Production Impact | Diagnostic & Mitigation Strategy |
|---|---|---|---|
| Missing Kernel Config | CONFIG_TASKSTATS omitted from build |
iotop aborts on launch |
Verify flags in /proc/config.gz and boot parameters |
| Privilege Boundaries | Missing CAP_NET_ADMIN capability |
Netlink socket bind failure | Grant targeted Linux capabilities using setcap |
| Polling Overhead | Excessive polling frequency (-d < 1) |
Scheduler lock contention | Enforce minimum interval of 2 seconds with -P flag |
| Page-Cache Illusions | Asynchronous buffered writes | Disconnect between write rate and %IO |
Evaluate %IO delay before assuming physical saturation |
1. Missing Kernel Taskstats Configuration
If iotop is executed on a custom enterprise kernel or stripped-down container host where task accounting was omitted to reduce binary footprint, the utility will fail on launch:
CONFIG_TASK_DELAY_ACCT not enabled in kernel, cannot determine SWAPIN/IO %
Resolution: Verify kernel capabilities before relying on the tool by inspecting /boot/config-$(uname -r) or /proc/config.gz:
zgrep -E 'CONFIG_TASKSTATS|CONFIG_TASK_DELAY_ACCT|CONFIG_TASK_IO_ACCOUNTING' /proc/config.gz
Ensure all three directives evaluate to =y. Additionally, verify delay accounting has not been deactivated at boot time via the kernel parameter sysctl kernel.task_delayacct or nodelayacct in the bootloader.
2. Privilege Escalation and Linux Capability Boundaries
Running iotop as an unprivileged user fails immediately because binding to the Netlink TASKSTATS family requires administrative privileges. However, granting full root execution violates security best practices.
Netlink error: Operation not permitted
Resolution: Rather than granting full setuid root, assign targeted Linux capabilities to the iotop binary using setcap(8):
# Assign CAP_NET_ADMIN to enable Netlink taskstat operations
sudo setcap cap_net_admin+ep $(which iotop)
(Note: Depending on whether a distribution uses the C or Python implementation of iotopβsuch as Debian, RHEL, or Arch LinuxβCAP_SYS_ADMIN or CAP_SYS_PTRACE may also be required to access /proc/[pid]/io).
3. Netlink Protocol Polling Overhead on Dense Multi-Threaded Nodes
On large-scale systems hosting thousands of active threads (such as massive Java application runtimes or Erlang BEAM nodes), launching iotop with aggressive sampling intervals (e.g., -d 0.1) introduces significant CPU overhead. The kernel must iterate through active task structures to serialize Netlink packets, causing lock contention in scheduler runqueues.
Remediation: In production, avoid sub-second sampling frequencies. Enforce minimum intervals of -d 2 or -d 5 and utilize the -P flag to aggregate taskstats by parent process, dramatically reducing Netlink serialization work.
4. The Page Cache Illusion: Synchronous vs. Asynchronous Storage Accounting
Engineers frequently misinterpret iotop metrics during asynchronous write operations. When an application calls write(), data is placed into the Linux kernel page cache (dirty memory) almost instantaneously. iotop will record a burst of DISK WRITE bandwidth for that process. However, if the application does not issue fsync() or fdatasync(), physical writes to NVMe or SATA blocks occur later via kernel background flusher threads ([kworker/uXX:X-flush]). A process with high write throughput is not necessarily stalled waiting on physical disk hardware unless its %IO column is simultaneously elevated.
Technical Reference: Essential Flag Matrix
| Flag | Long Argument | Type | Architectural Purpose |
|---|---|---|---|
-o |
--only |
Filter | Excludes all processes with zero read/write activity and zero I/O delay from the interface. |
-b |
--batch |
Mode | Disables the curses UI, formatting telemetry as standard plain text for pipelines and file logging. |
-n N |
--iter=N |
Control | Terminates execution automatically after $N$ discrete polling intervals. |
-d S |
--delay=S |
Interval | Sets the sleep duration ($S$ seconds) between kernel Netlink sampling cycles. |
-P |
--processes |
Aggregation | Aggregates child thread metrics under their parent Process Identifier (PID). |
-a |
--accumulated |
Accounting | Displays cumulative data volume transferred since tool launch rather than instantaneous throughput. |
-k |
--kilobytes |
Display | Enforces a static unit of KB/s across all throughput columns, preventing auto-scaling artifacts. |
-t |
--time |
Metadata | Prepends a high-precision timestamp to every output row in batch mode. |
-p P |
--pid=P |
Filter | Limits kernel taskstat querying to one or more explicit process identifiers. |
-u U |
--user=U |
Filter | Filters accounting records to processes belonging exclusively to user $U$. |
Today's Takeaway
The storage subsystem remains the most latency-sensitive and contention-prone layer of the Linux infrastructure stack. When disk queues back up and load averages spike, open a terminal on your local workstation or staging server right now and run sudo iotop -o -P -d 2. Take five minutes to observe the relationship between DISK READ, DISK WRITE, and the %IO wait percentage across your active applications; establishing this baseline during normal operations ensures that when a midnight storage bottleneck hits production, you can pinpoint the culprit in seconds.