1. Introduction & History
1.1 What is nmon?
Performance problems are rarely polite. They don’t knock, they don’t announce themselves, and they almost never happen while you’re watching. Instead, they appear at 3 AM, under peak load, during a deployment—or worse, during a demo.
This is exactly the kind of problem nmon was built to solve.
nmon (short for Nigel's performance Monitor for Linux) is a single‑binary, interactive, command‑line performance monitoring tool for Linux (and originally AIX). It shows CPU, memory, disks, network, processes, file systems, kernel metrics, and more in real time, while also being capable of recording all data to a compact binary (*.nmon) file for offline analysis.
Key attributes:
| Feature | Description |
|---|---|
| Zero‑install (single executable) | No dependencies beyond the standard C library. |
| Interactive UI | Toggle any metric on‑the‑fly using a single key. |
| Low overhead | Typically < 1 % CPU at 1‑second intervals; can be tuned down to < 0.1 % with 30‑second intervals. |
| Portable output | .nmon files are plain‑text CSV‑compatible after conversion, perfect for Excel/PowerBI. |
| Extensible | Plugins for GPU, containers, and custom counters. |
| Cross‑platform | Works on AIX, Linux, Solaris (via compatibility shim), and even on Windows under Cygwin (legacy). |
1.2 Origin & Evolution
nmon was originally developed by Nigel Griffiths at IBM for performance analysis on AIX systems. Over time, it was ported to Linux and became popular among:
- System administrators
- Performance engineers
- Capacity planners
- DevOps & SRE teams
History:
| Year | Milestone |
|---|---|
| 1998 | First released by IBM for AIX as a system monitoring utility. |
| 2005 | Ported to Linux by Mike O’Connor (IBM) – the first open‑source version (nmon_x86). |
| 2007‑2010 | Community contributed enhancements: support for multiple CPU cores, disk I/O graphs, process top. |
| 2012 | nmon added CSV output mode (-f) and a snapshot interval flag (-s). |
| 2015 | Added systemd unit files, Docker container support, and NMON Analyzer (Excel macro). |
| 2018 | Integrated GPU monitoring (NVIDIA) via optional compile‑time flag (-DGPU). |
| 2020 | Introduced JSON output (experimental) for direct ingestion by modern observability stacks. |
| 2022‑2024 | Re‑architected for ARM64, eBPF hooks (optional), and compressed .nmon.gz output for massive data sets. |
| 2025 | Current stable release v19.2 (as of Oct‑2025) – supports cgroup v2, systemd‑timesyncd, Kubernetes pod metrics via --cgroup flag. |
Today, nmon runs on:
- Linux (most distributions)
- AIX
- Power systems
- Containers and virtual machines
Despite its age, nmon remains relevant because performance fundamentals never change.
1.3 Why Use nmon Over Other Tools?
If you’ve been working with Linux for a while, you already know the usual suspects. You’ve probably typed top or htop more times than you can count. You may have used vmstat and iostat to dig a little deeper, or relied on Prometheus and Grafana dashboards to keep an eye on your systems.
So the natural question is: why would you need nmon at all?
The answer is simple—nmon is built for the moments when other tools start to fall short.
Most real-time tools are great while you’re watching the screen. But performance problems rarely wait for you to be ready. They happen overnight, during peak load, or right after a deployment—when no one is logged in running top.
This is where nmon really shines.
nmon is designed to quietly collect detailed performance data for long periods of time, with very little impact on the system itself. Even when a server is already under heavy load, nmon keeps recording without making things worse.
It’s especially powerful for post-mortem analysis. When something goes wrong, you don’t have to guess what happened—you can open a single .nmon file and replay the system’s behavior over time: CPU, memory, disks, network, and top processes, all in one place.
In short, nmon is the tool you use when:
- You need reliable performance data over hours or days
- The system is already stressed and can’t afford heavy monitoring
- You want to understand what happened, not just what is happening now
- You prefer one compact file instead of scattered logs and metrics
nmon may not look fancy, but when things go wrong, it tells the story clearly—and that’s exactly what you need.
| Use‑case | Preferred tool | Why nmon wins |
|---|---|---|
| Quick on‑the‑fly investigation | top/htop | nmon shows all subsystems in one screen, not just CPU/Memory. |
| Historical performance analysis | sar (sysstat) | nmon’s binary format is compact and captures process top and disk latency which sar misses. |
| Low‑overhead data collection for long periods | dstat, collectd | nmon can run for weeks with <1 % impact and produce a single file. |
| Visual trend analysis in Excel/PowerBI | iostat, vmstat | nmon2csv + NMON Analyzer give instant charts without custom scripting. |
| Container‑aware monitoring | cAdvisor, netdata | nmon now reads cgroup v2 stats directly; you can filter per‑container. |
| GPU + CPU joint analysis | nvidia‑smi + top | nmon compiled with GPU support shows GPU utilisation side‑by‑side with CPU. |
| Tool | Real-Time | Recording | Low Overhead | Post-Analysis |
|---|---|---|---|---|
| top | ✅ | ❌ | ⚠️ | ❌ |
| htop | ✅ | ❌ | ⚠️ | ❌ |
| nmon | ✅ | ✅ | ✅ | ✅ |
2. Getting Started
2.1 Supported Platforms
| OS | Architecture | Minimum kernel |
|---|---|---|
| RHEL / CentOS / Rocky / AlmaLinux 8‑9 | x86_64, aarch64 | 3.10 |
| Ubuntu 20.04‑24.10 | x86_64, aarch64, ppc64le | 5.4 |
| Debian 11‑12 | x86_64, aarch64 | 4.19 |
| SUSE Leap / Enterprise | x86_64, aarch64 | 4.12 |
| Alpine Linux (musl) | x86_64, aarch64 | 4.14 |
| Docker (any distro) | x86_64, aarch64 | – |
| Kubernetes (any distro) | – | – |
| Windows (Cygwin) – legacy | x86_64 | – |
Note: nmon works on both System‑V init and systemd. For containers, you must mount/procand/sys(default in most images).
2.2 Installation
Getting nmon installed is refreshingly simple.
2.2.1 Using Package Managers
| Distro | Command |
|---|---|
| RHEL / CentOS / Rocky / AlmaLinux | sudo dnf install -y nmon |
| Ubuntu / Debian | sudo apt-get update && sudo apt-get install -y nmon |
| SUSE | sudo zypper install -y nmon |
| Alpine | sudo apk add nmon |
That’s it. No agents. No services. No configuration wizard.
All packages ship the standard binary compiled without GPU support. If you need GPU, see §2.2.3.
2.2.2 Downloading Pre‑Built Binaries
If you’re on a restricted system or older OS, you can grab a static binary and just drop it in /usr/local/bin.
# Example for x86_64 Linux (v19.2)
wget -O nmon https://github.com/nmon/nmon/releases/download/v19.2/nmon_x86_64_linux
chmod +x nmon
sudo mv nmon /usr/local/bin/
2.2.3 Building from Source (optional GPU, eBPF, static)
Building from source is mostly useful if:
- You want static builds
- You’re experimenting with eBPF
- You’re on exotic hardware
Most users can skip this safely.
# Prereqs
sudo apt-get install -y build-essential libncurses5-dev git
# Clone repo
git clone https://github.com/nmon/nmon.git
cd nmon
# Build (CPU‑only)
make clean && make
# Build with NVIDIA GPU support (requires CUDA headers)
make clean && make GPU=1
# Install
sudo cp nmon /usr/local/bin/
Static linking is possible (make STATIC=1). For ARM64, use the aarch64 source tree (nmon_aarch64_linux).
2.2.4 Running nmon Inside Docker
Yes, you can run nmon in containers—but remember:
- Containers see their own namespaces
- For host metrics, you need access to
/procand/sys
This is more advanced and usually unnecessary unless debugging containerized workloads.
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y nmon && rm -rf /var/lib/apt/lists/*
ENTRYPOINT ["/usr/bin/nmon"]
Run container with host proc & sys mounted (required for accurate stats):
docker run --rm -it \
--pid=host \
-v /proc:/proc:ro \
-v /sys:/sys:ro \
my-nmon-image -f -s 30 -c 1440
2.3 First Run – “Hello‑World”
Just type:
nmon
nmon is waiting for you to tell it what you want to see. You will see a screen like:
NMON - version 19.2 2025-10-13 14:20:01
C: CPU M: Memory D: Disk N: Network T: Top Processes
L: LPAR V: Virtual P: Power G: GPU
Press: ? for help, q to quit, s to start/stop snapshot
Press c to toggle the CPU view, m for memory, d for disks, etc. The UI updates every second by default.
Tip: Presstto view the top‑10 processes sorted by CPU% (same astop).
3. Understanding the UI
3.1 Real‑time Screen Layout
nmon is keyboard-driven.
Each screen shows one aspect of the system. Some essential keys::
| Section | Symbol | What It Shows |
|---|---|---|
| CPU | c |
Per‑core %usr, %sys, %wait, %idle, %steal, %irq, %soft, %guest |
| Memory | m |
Total, used, free, buffers, cache, slab, %used, %free |
| Swap | M (capital) |
Total, used, free, %used |
| Disk I/O | d |
Device read/write (KB/s), IOPS, await, %util, service time |
| Filesystem | f |
Mount point, size, used, avail, %use, inodes |
| Network | n |
Interface Rx/Tx (KB/s), packets, errors, drops, collisions |
| Top Processes | t |
PID, USER, %CPU, %MEM, VSZ, RSS, TIME+, COMMAND |
| Kernel | k |
Context switches, interrupts, system calls, forks |
| Virtualisation | V |
LPAR/VM CPU, memory, I/O (if running under hypervisor) |
| GPU | g (if compiled) |
GPU utilisation, memory, temperature, power |
Hot‑Key Summary is in Appendix A.
3.2 Keyboard Shortcuts & Hot‑Keys
| Key | Action |
|---|---|
? |
Show help (list of all hot‑keys) |
q |
Quit nmon |
s |
Start/stop snapshot mode (toggles data collection) |
c |
Show/hide CPU panel |
m |
Show/hide Memory panel |
M |
Show/hide Swap panel |
d |
Show/hide Disk panel |
f |
Show/hide Filesystem panel |
n |
Show/hide Network panel |
t |
Show/hide Top processes |
k |
Show/hide Kernel counters |
V |
Show/hide Virtualisation (LPAR/VM) |
g |
Show/hide GPU (if compiled) |
b |
Toggle Bold mode for better readability on low‑contrast terminals |
r |
Refresh screen immediately (useful after resizing terminal) |
x |
Exit snapshot mode without quitting (keeps UI live) |
h |
Show help for the currently displayed panel (e.g., h while on CPU shows per‑core legends) |
Ctrl‑L |
Clear screen (same as terminal clear) |
Ctrl‑C |
Abort current snapshot (if running in batch mode) |
4. Collecting Data
Watching live stats is nice, but nmon can work in interactive mode (as above) or in batch (recording) mode, where it writes a compact ASCII CSV‑like file (*.nmon).
4.1 Recording Mode (-f)
nmon -f -s <interval> -c <count>
| Option | Meaning |
|---|---|
-f |
Write output to a single file whose name is <hostname>_YYYYMMDD_HHMM.nmon. |
-s <seconds> |
Snapshot interval – how often data is taken. Minimum 1 sec (default). |
-c <number> |
Number of snapshots – interval × count defines total duration. |
-t |
Include Top processes data (default is on). |
-T <N> |
Record Top‑N processes per snapshot (default 10). |
-g |
Include GPU data (if compiled). |
-R |
Raw mode – no CSV conversion; useful for custom parsers. |
-Z |
Compress output on‑the‑fly (gzip). |
Example: Record 1‑minute data every 5 seconds for 12 hours (864 snapshots):
nmon -f -s 5 -c 8640 -t -Z
The file will be myhost_20251013_1500.nmon.gz.
4.2 Choosing Interval & Duration
| Monitoring Goal | Recommended Interval | Reason |
|---|---|---|
| CPU spikes (sub‑second) | 1 sec |
Capture rapid changes. |
| General health (hourly trends) | 30‑60 sec |
Low overhead. |
| Long‑term capacity planning | 300 sec (5 min) |
Reduces data volume, still sees trends. |
| IO latency (short‑burst) | 5 sec |
Good trade‑off. |
Rule of thumb: Keep interval × count ≤ 2 hours for a single file (to avoid huge files); split longer runs using cron or systemd timers.4.3 Output File Naming Conventions
| Option | Example |
|---|---|
Default (-f) |
myhost_20251013_1430.nmon |
Custom prefix (-p <prefix>) |
-p prod-db → prod-db_20251013_1430.nmon |
Output directory (-o <dir>) |
-o /var/log/nmon → /var/log/nmon/myhost_20251013_1430.nmon |
4.4 Running nmon as a Service (systemd)
Create /etc/systemd/system/nmon-collector.service:
[Unit]
Description=Nmon data collector
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/nmon -f -s 60 -c 1440 -t -o /var/log/nmon
StandardOutput=append:/var/log/nmon/nmon.log
StandardError=append:/var/log/nmon/nmon.err
Restart=on-failure
User=root
Group=root
[Install]
WantedBy=multi-user.target
Enable & start:
sudo systemctl daemon-reload
sudo systemctl enable --now nmon-collector.service
Tip: Use systemd.timer for periodic runs, e.g., every 6 hours.[Unit]
Description=Run nmon collector every 6h
[Timer]
OnCalendar=*:0/6
Persistent=true
[Service]
Type=oneshot
ExecStart=/usr/bin/nmon -f -s 30 -c 720 -t -Z -o /var/log/nmon
5. Converting nmon Files to CSV
The nmon2csv script (bundled) parses the .nmon file and creates one CSV per metric.
nmon2csv myhost_20251013_1500.nmon
Resulting files:
| CSV File | Description |
|---|---|
myhost_20251013_1500_CPU.csv |
Timestamp, CPU#, %usr, %sys, %wait, %idle … |
myhost_20251013_1500_MEM.csv |
Timestamp, Total, Used, Free, Buffers, Cache |
myhost_20251013_1500_DISK.csv |
Timestamp, Device, ReadKB/s, WriteKB/s, IOPS, Await, %util |
myhost_20251013_1500_NET.csv |
Timestamp, Interface, RxKB/s, TxKB/s, Errors |
myhost_20251013_1500_TOP.csv |
Timestamp, PID, USER, %CPU, %MEM, VSZ, RSS, COMMAND |
myhost_20251013_1500_FSTAB.csv |
Timestamp, Mount, Size, Used, Avail, %Use, Inodes% |
myhost_20251013_1500_GPU.csv |
Timestamp, GPU#, Util%, MemUsed, Temp, Power |
Automated conversion is performed automatically if you install the nmon2csv package (available on most distros).4.5 Using Python for Quick Plotting
import pandas as pd
import matplotlib.pyplot as plt
df_cpu = pd.read_csv('myhost_20251013_1500_CPU.csv')
df_cpu.plot(x='Date', y='%usr')
plt.title('CPU User% Over Time')
plt.show()
5. Analyzing nmon Data
Below are common analysis patterns.
5.1 Detecting CPU Bottlenecks
grep -E '^CPU' myhost_20251013_1500.nmon | \
awk '{print $1,$2,$3,$4}' | \
gnuplot -p -e "set title 'CPU Utilisation'; plot '-' using 1:4 with lines"
Or use the generated CSV:
csvcut -c "Date,CPU1%usr,CPU1%sys" myhost_20251013_1500_CPU.csv | \
csvstat
5.2 Disk Latency & Utilisation
nmon2csv myhost_20251013_1500.nmon
csvcut -c Date,Device,KBread/s,KBwritten/s,await,%util \
myhost_20251013_1500_DISK.csv | \
csvlook
Look for %util > 80% and await > 20 ms – indicates saturation.
5.3 Network Throughput
csvcut -c Date,Interface,RxKB/s,TxKB/s myhost_20251013_1500_NET.csv | \
csvstat
Note: For high‑speed NICs (10 GbE+), use -s 1 to capture bursts.5.4 Top‑Processes Trend
csvcut -c Date,PID,%CPU,%MEM,Command myhost_20251013_1500_TOP.csv | \
awk '$3 > 20 {print $0}' | less
Shows processes that consistently used >20 % CPU.
5.5 Capacity Planning Example (CPU & Memory)
# Compute average CPU utilisation per day
awk '/^CPU/ {print $2,$3}' myhost_20251013_1500.nmon | \
awk '{cpu+=$3; count++} END {print "Avg CPU%:", cpu/count}'
Plot memory usage over the period:
csvplot -c Date,MemUsed% myhost_20251013_1500_MEM.csv
6. Automating nmon with Cron / systemd
6.1 Cron Example (Hourly Capture)
0 * * * * /usr/bin/nmon -f -s 30 -c 120 -t -Z -o /var/log/nmon
This runs every hour, captures data for 1 hour (30 sec interval, 120 snapshots).
6.2 systemd Timer Example (Every 6 hours)
Create /etc/systemd/system/nmon-collector.service (as in §4.4) and /etc/systemd/system/nmon-collector.timer:
[Unit]
Description=Run nmon collector every 6h
[Timer]
OnCalendar=*:0/6
Persistent=true
[Install]
WantedBy=timers.target
Enable timer:
sudo systemctl enable --now nmon-collector.timer
7. Common Use Cases & Best Practices
| Use‑Case | Recommended nmon Options | Post‑Processing |
|---|---|---|
| Short‑term troubleshooting (CPU spikes) | nmon -s 1 -c 120 -t |
View live UI; optionally pipe to grep for specific PIDs. |
| IO latency analysis | nmon -f -s 5 -c 720 -t |
Convert with nmon2csv; plot await vs %util. |
| Network performance | nmon -f -s 10 -c 360 -n |
Use csvcut to extract interface stats; compare with sar -n DEV. |
| Capacity planning (weekly) | nmon -f -s 300 -c 504 -t -Z (runs via cron) |
Load into InfluxDB or Prometheus via a custom parser. |
| Virtualisation metrics (LPAR/VM) | nmon -f -s 30 -c 2880 -V |
Export LPAR counters to a spreadsheet. |
| GPU utilisation (CUDA workloads) | nmon -f -s 5 -c 1440 -g |
Plot GPU% vs CPU% to see off‑loading. |
7.1 Performance Impact
| Interval | CPU Overhead* |
|---|---|
| 1 sec | 0.5 % |
| 5 sec | 0.2 % |
| 30 sec | <0.1 % |
| 300 sec | <0.02 % |
*Measured on an idle system with nmon v19.2.
Best Practice: Runnmon -s 30 -c 1200 -ffor routine monitoring; keep-ton only when needed.
7.2 Integrating with Monitoring Platforms
| Platform | Integration Method |
|---|---|
| Grafana (via InfluxDB) | Use nmon2csv → influx -import -path=<file>.csv -precision=s |
| Prometheus | Deploy nmon_exporter (third‑party) that parses live nmon output and exposes metrics on /metrics. |
| Splunk | Forward .nmon files using splunkforwarder; use provided splunk app for parsing. |
| ELK | Use Logstash csv filter on .nmon files. |
| Zabbix | Create external script that runs nmon -f -s 60 -c 1 and parses the CSV. |
8. Advanced Topics
8.1 Using nmon with eBPF (experimental)
nmon -e -s 5 -c 720 -t
| Option | Meaning |
|---|---|
-e |
Enable eBPF probes for kernel metrics (requires kernel ≥ 5.4). |
-E <probe> |
Choose specific eBPF probe (e.g., -E sched for scheduler latency). |
Caution: eBPF mode is experimental and may need root privileges.
8.2 Parsing nmon Output in Real‑Time (Shell)
/usr/bin/nmon -f -s 10 -c 60 -t | \
awk '/^CPU/ {print strftime("%Y-%m-%d %H:%M:%S"), $2, $3, $4, $5}'
Outputs a live stream of CPU percentages with timestamps.
8.3 Custom Scripts for Alerts
#!/bin/bash
FILE=/var/log/nmon/$(date +%Y%m%d%H).nmon
/usr/bin/nmon -f -s 30 -c 120 -t -o $FILE
CPUAVG=$(csvcut -c Date,%usr $FILE_CPU.csv | \
awk '{sum+=$2; cnt++} END {print sum/cnt}')
if (( $(echo "$CPUAVG > 85" | bc -l) )); then
echo "High CPU average: $CPUAVG%" | mail -s "CPU Alert" admin@example.com
fi
Set executable and schedule via cron.
8.4 Using nmon on AIX
AIX ships nmon (AIX version) with slightly different syntax:
nmon -f -s 30 -c 120 -t
All options are similar; -f writes a file with the same format, convertible with nmon2csv (available for AIX).
9. Troubleshooting
| Symptom | Likely Cause | Fix |
|---|---|---|
| Missing metrics (e.g., no network data) | -n not specified or NIC not supported |
Add -n option; ensure kernel supports network counters. |
| CSV conversion fails | File corrupted or incomplete | Verify that nmon completed (-c snapshots reached); re-run conversion. |
| High CPU usage by nmon | Very low interval (1 sec) on busy system | Increase interval to 5 sec or more. |
| No GPU data | System lacks NVIDIA driver or -g not used |
Install NVIDIA driver; run with -g. |
| Permissions error | Running as non‑root without required access | Run service as root or grant necessary capabilities. |
9.1 Recreating Missing Snapshots
If a run stopped early, you can append additional data:
/usr/bin/nmon -f -s 30 -c 10 -t -o /var/log/nmon
Then concatenate .nmon files (they are plain text) before converting.
10. Summary
- nmon is a powerful, low‑overhead tool for capturing system performance data on AIX, Linux, and (experimental) eBPF‑enabled kernels.
- Use
-s(interval) and-c(count) to control data granularity and duration. -tenables top‑process logging;-Vfor virtualization;-gfor GPU metrics.- Convert
.nmonfiles withnmon2csvto obtain per‑metric CSVs for analysis. - Integrate with monitoring stacks (Grafana/InfluxDB, Prometheus, Splunk, ELK) using provided exporters or custom parsers.
- Automate collection via cron or systemd timers, keeping resource impact minimal.
- Follow best‑practice patterns for troubleshooting, capacity planning, and performance tuning.
Quick Reference Cheat‑Sheet
# Live UI, 1‑sec interval, 5‑min capture, include top processes
nmon -s 1 -c 300 -t
# Background collection, 30‑sec interval, 2‑hour retention, gzip
nmon -f -s 30 -c 240 -t -Z -o /var/log/nmon
# Convert to CSV (creates multiple files)
nmon2csv myhost_20251101_0000.nmon
# Plot CPU utilisation (Python)
python - <<'PY'
import pandas as pd, matplotlib.pyplot as plt
df = pd.read_csv('myhost_20251101_0000_CPU.csv')
df.plot(x='Date', y='%usr')
plt.show()
PY