When a backup, video conversion or big build runs on the same server as your website, it competes for CPU and disk. Linux lets you tell the scheduler which processes matter more. nice values control CPU priority, and ionice controls disk priority. Used together, they keep heavy background jobs from slowing down your users.

Nice values

Every process has a nice value from −20 (highest priority) to 19 (lowest). The default is 0. A “nicer” process (higher number) is more polite. It yields CPU to others when they need it.

Nice values only matter when the CPU is contended. On an idle server, a nice 19 process still uses all available CPU.

See current values:

ps -eo pid,ni,pri,comm --sort=-ni | head
top          # NI column

Start a command with a priority: nice

nice -n 19 tar -czf /backup/site.tar.gz /var/www/site
nice -n 10 ./build.sh
nice ./script.sh             # default: +10

Only root can set negative values (higher priority):

sudo nice -n -5 ./important-job

Change a running process: renice

renice -n 15 -p 12345          # one process
renice -n 10 -u backupuser     # all processes of a user
sudo renice -n -5 -p 12345     # raise priority (root only)

Normal users can only make their processes nicer, not less nice.

Disk priority: ionice

CPU isn’t usually the bottleneck for backups and file operations. Disk I/O is. ionice sets the I/O scheduling class:

Class Option Meaning
Idle -c3 Only gets disk time when nobody else needs it
Best-effort -c2 -n0..7 Default class, 0 = highest within the class
Realtime -c1 Always first. Root only, can starve the system
ionice -c3 rsync -a /var/www/ /backup/www/
ionice -c2 -n7 -p 12345            # change a running process

Combine both for heavy background jobs:

nice -n 19 ionice -c3 tar -czf /backup/site.tar.gz /var/www/site

ionice classes are fully honoured by the BFQ scheduler. With mq-deadline or none, the default on many virtual and NVMe disks, the effect is limited. Check the scheduler with cat /sys/block/vda/queue/scheduler. For those, scheduling jobs off-peak or rate-limiting them (rsync --bwlimit, pv -L) is more reliable.

Cron jobs

30 3 * * * nice -n 19 ionice -c3 /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1

See crontab.

systemd services and timers

Set priorities in the unit, so they apply however the service starts:

[Service]
Nice=10
IOSchedulingClass=idle
CPUSchedulingPolicy=batch

For stronger, guaranteed limits, use cgroup settings. They work even when nice values aren’t enough:

[Service]
CPUWeight=20          # default 100; lower = less CPU share under contention
IOWeight=20           # default 100
CPUQuota=50%          # hard cap: at most half a core

CPUQuota limits the job even when the CPU is idle, so use it for jobs that must never hog the server. See systemd unit files and systemd timers.

Throttle a running service on the fly:

sudo systemctl set-property --runtime myjob.service CPUQuota=30%

Containers

docker run --cpus=1 --cpu-shares=256 …
docker update --cpus=0.5 container-name

See Docker CPU and memory limits.

Practical examples

Job Command
Nightly backup nice -n 19 ionice -c3 backup.sh
Image or video processing queue Nice=10 + CPUWeight=50 in the worker unit
Compiling on a production box nice -n 19 make -j2
Database dump nice -n 10 ionice -c2 -n7 mysqldump …
Log compression (logrotate) Often already niced. Check its timer

What nice doesn’t do

  • It doesn’t limit memory. Use MemoryMax= or container limits.
  • It doesn’t stop a process from using an idle CPU. Use CPUQuota for a hard cap.
  • Negative nice values on everything you care about cancel each other out. Lower the priority of background work instead of raising everything else.

Quick reference

Task Command
Start low priority nice -n 19 cmd
Change running renice -n 15 -p PID
Disk idle class ionice -c3 cmd
Both nice -n 19 ionice -c3 cmd
In systemd Nice=10, IOSchedulingClass=idle
Hard CPU cap CPUQuota=50%
See nice values ps -eo pid,ni,comm

Related: load average and iostat.

  • Linux
  • Performance
  • Command Line