ionice sets or shows a process's I/O scheduling class and priority — the disk equivalent of nice. Typical use: keep backups, rsync, find, or log compression from making the rest of the system sluggish. It pairs naturally with nice/renice for CPU, and with rsync backup jobs run from cron, so they don't compete with foreground work.
Syntax¶
ionice [-c class] [-n level] [-t] -p PID... # change running processes
ionice [-c class] [-n level] [-t] -P PGID... # process groups
ionice [-c class] [-n level] [-t] -u UID... # all of a user's processes
ionice [-c class] [-n level] [-t] COMMAND [ARGS] # start a command
ionice -p PID # show current setting
Classes¶
-c |
Class | Behaviour |
|---|---|---|
0 |
none | Default. Priority is derived from the CPU nice value: (nice + 20) / 5 within best-effort |
1 |
realtime | Always served first. Levels 0–7. Root only — can starve everything else, including the system |
2 |
best-effort | Normal class. Levels 0 (highest) – 7 (lowest), default 4 |
3 |
idle | Only gets disk time when nobody else wants it. No level. No root needed |
-n sets the level (0–7) for classes 1 and 2. -t ignores failures to set the class (useful in scripts).
Examples¶
# Run a backup only when the disk is otherwise idle
ionice -c3 tar czf /backup/home.tar.gz /home
# Lowest best-effort priority, combined with low CPU priority
nice -n 19 ionice -c2 -n7 rsync -a /data/ /mnt/backup/
# Check a process
ionice -p 1234
# best-effort: prio 4
# Demote a running process
sudo ionice -c3 -p 1234
# Demote everything a user is running
sudo ionice -c2 -n7 -u builduser
# Give a critical database real-time I/O (careful)
sudo ionice -c1 -n0 -p $(pgrep -o postgres)
When it actually works¶
ionice only sets a hint; the block I/O scheduler decides whether to honour it.
cat /sys/block/sda/queue/scheduler
# none mq-deadline kyber [bfq]
| Scheduler | Honours ionice? |
|---|---|
bfq |
Yes — classes and levels |
mq-deadline |
Partially — separates realtime / best-effort / idle classes; levels within a class are mostly ignored |
kyber, none |
No |
NVMe devices default to none, so ionice usually does nothing on them. Switch to bfq if you need it (at some throughput cost):
echo bfq | sudo tee /sys/block/nvme0n1/queue/scheduler
The old cfq scheduler that ionice was designed around was removed in kernel 5.0.
The buffered-write caveat¶
Most writes go into the page cache and are flushed later by kernel writeback threads — not by your process. The I/O priority mostly applies to reads and direct/synchronous writes. An ionice -c3 process doing heavy buffered writes can still saturate the disk.
For real write throttling, use cgroup v2 limits instead (below).
Better option on systemd systems: cgroups¶
The cgroup v2 io controller works regardless of scheduler for limits, and accounts for writeback:
# One-off command with lower I/O weight (default 100, range 1–10000)
sudo systemd-run --scope -p IOWeight=10 rsync -a /data/ /mnt/backup/
# Hard bandwidth cap
sudo systemd-run --scope -p "IOWriteBandwidthMax=/dev/sda 20M" dd if=/dev/zero of=/tmp/big bs=1M count=2000
In a unit file:
[Service]
IOSchedulingClass=idle # ionice equivalent (best-effort, realtime, idle)
IOSchedulingPriority=7 # 0-7
IOWeight=10 # cgroup weight (BFQ honours it)
IOReadBandwidthMax=/dev/sda 50M
IOWeight relies on BFQ for proportional sharing; the *BandwidthMax / *IOPSMax limits work with any scheduler.
Quick reference¶
| Goal | Command |
|---|---|
| Show priority | ionice -p PID |
| Background job | ionice -c3 CMD |
| Low priority, still progresses | ionice -c2 -n7 CMD |
| Low CPU + I/O | nice -n19 ionice -c3 CMD |
| Check scheduler | cat /sys/block/DEV/queue/scheduler |
| Hard limit instead | systemd-run --scope -p "IOWriteBandwidthMax=DEV RATE" CMD |
See also¶
man 1 ionice,man 2 ioprio_setnice,renice,chrt,taskset- rsync, cron
- The Linux Kernel — I/O schedulers and cgroups
- Kernel docs:
Documentation/block/ioprio.rst,Documentation/admin-guide/cgroup-v2.rst