How to Use the Linux iostat Command to Diagnose Hard Drive I/O Bottlenecks

The Invisible Bottleneck

When a Linux server runs catastrophically slow, junior administrators immediately check the top or htop commands. They look at the CPU utilization, see that it is sitting at a healthy 15%, check the RAM, see that 10GB is free, and conclude that the server is perfectly fine. Meanwhile, the website hosted on the server is taking 30 seconds to load a simple page.

What top obscures is the most common and devastating bottleneck in enterprise computing: Storage I/O (Input/Output). If a database is trying to read 5,000 random rows from a slow, failing mechanical hard drive, the CPU cannot execute the code; it must physically wait for the hard drive to spin to the correct sector and return the data. During this time, the CPU is essentially “frozen.”

To definitively prove that a server is suffering from disk latency, Linux engineers use the iostat (Input/Output Statistics) command. iostat interrogates the kernel block layer, providing deep, real-time mathematical telemetry on exactly how many megabytes per second the hard drives are processing, and crucially, exactly how long the CPU is wasting time waiting for them.

Step 1: Installing the sysstat Package

The iostat command is not a standalone executable; it is part of the sysstat bundle, which is usually not installed by default on minimal server images.

sudo apt update
sudo apt install sysstat -y

Step 2: The CPU Wait Metric (%iowait)

Before you look at the hard drives, you must look at the CPU to see if it is experiencing storage starvation.

Run the basic iostat command:

iostat

The first block of output displays the CPU utilization. Pay absolute attention to the %iowait column.

%iowait represents the percentage of time that the CPU was completely idle, doing absolutely no work, strictly because it was forced to wait for an outstanding disk read/write request to complete.

  • If %iowait is 0.5%, your storage is fast and healthy.
  • If %iowait is 15% or higher continuously, your hard drives are catastrophically bottlenecking your entire server architecture. Upgrading to a faster CPU will not fix the problem; you must upgrade the storage to NVMe or SSD.

Step 3: Continuous Live Monitoring

Running iostat once only provides a historical average since the server booted. To troubleshoot an active incident, you must force iostat to stream live data.

Use the syntax iostat [interval] [count]. To display the statistics every 2 seconds, indefinitely:

iostat -dz 2

Decoding the Flags:

  • -d (Disk): Hides the CPU summary and only shows the hard drive metrics.
  • -z (Zero): Only prints drives that actually had I/O activity during that 2-second window. If you have 50 drives in a SAN and only one is writing, it hides the 49 idle ones, keeping the terminal readable.

Step 4: Interpreting the Extended Disk Metrics (-x)

The standard output only shows generic MB/s data. To truly diagnose a failing drive, you need the extended metrics.

iostat -dxz 2

This expands the output into a massive table. These are the four critical columns every administrator must understand:

  1. r/s and w/s (Reads/Writes per Second): This is your IOPS. If an enterprise NVMe SSD is pushing 50,000 IOPS, it is healthy. If a legacy SATA drive is struggling to push 150 IOPS and the application is demanding 500, you have found the bottleneck.
  2. rkB/s and wkB/s (Read/Write Kilobytes per Second): This is your Throughput (Bandwidth). IOPS measures the number of requests; Throughput measures the size of the data. A server performing a massive sequential backup might have low IOPS (10 large requests) but massive Throughput (500 MB/s).
  3. await (Average Wait Time): The absolute most important metric. This is the average time (in milliseconds) it took for a disk request to be fully processed (including time spent waiting in the queue). For modern SSDs, this should be under 5ms. If your await spikes to 150ms, the hard drive is severely overloaded or physically dying.
  4. %util (Utilization Percentage): The percentage of time the physical disk was actively doing work. If a drive sits at 100% utilization continuously, it has reached its absolute maximum physical capability. It cannot accept any more traffic.

Step 5: Correlating Metrics to Real-World Problems

By analyzing these four columns together, you can diagnose exact architectural failures:

  • Scenario A (The Overloaded Drive): %util is at 100%, await is 250ms, but throughput is only 2 MB/s. This means the disk is fighting thousands of tiny, random reads (high IOPS, low throughput). The mechanical arm of the drive is thrashing. You must move the database to an SSD, which has no moving parts.
  • Scenario B (The Hardware Failure): %util is at 100%, but both IOPS (r/s) and Throughput are virtually zero. The disk isn’t doing any work, but it claims to be 100% busy. The disk controller has likely crashed, or the SATA cable is damaged, causing the kernel to endlessly retry failed commands.

Conclusion

CPU and RAM metrics present an incomplete picture of Linux server health. By leveraging the iostat command and understanding the interplay between %iowait, IOPS, and latency (await), system administrators can scientifically prove when legacy storage arrays or failing hardware are quietly strangling the performance of their mission-critical applications.

RELATED POSTS

  • How to Use the Linux journalctl Command to Read systemd Logs
  • How to Use the Linux file Command to Identify File Types
  • How to Use the patch Command to Apply Code Changes in Linux
  • How to View the Contents of a Compressed Archive Using the zcat Command in Linux
  • How to Use the diff Command to Compare Two Text Files Line by Line in Linux
  • Get the best tech tips delivered straight to your inbox.

    Join thousands of readers mastering Apple, Google, Microsoft, and Linux.