Introduction: When Your Backup Job Kills Your Server
A few summers back, I added a fancy new NAS to my homelab and decided to set up nightly rsync backups for the small VPS that hosted my blog. Smart move, right? Except I scheduled the job at 2 AM without thinking, and the next morning a friend in Australia messaged me that the site had been crawling. Turns out my “tiny” backup was happily eating 90% of the CPU and most of the disk I/O while my web server gasped for air. That single mistake is why I learned how to use nice and renice in Linux — and why I now wrap nearly every background script in them.

The fix wasn’t to kill the backup. It was to teach the kernel that the backup is less important than serving HTTP. That’s exactly what the nice and renice commands do. They don’t pause anything. They just tell Linux: “this process can wait its turn.” In this guide I’ll show you how to check process priority, launch new processes politely, renice the runaway ones you forgot about, and bake priority into your systemd services so you never get bitten the way I did.
Quick Answer: nice vs renice
nice sets the CPU priority of a new process when you launch it. renice changes the priority of a process that’s already running. Values range from -20 (greediest) to +19 (most polite). Default is 0. Only root can use negative values.
What Are nice and renice?
Both commands manipulate something called the nice value (or “niceness”) of a process. Think of niceness as how willing a process is to step aside for others. A high nice value means “I’m chill, let other people go first.” A low (or negative) nice value means “out of my way, I have work to do.”
Get a VPS from as low as $11/year! WOW!
nice: set priority at launch
The nice command runs a brand new program with a niceness value you specify. You wrap it around the command you want to run, and the new process is born already deprioritized (or prioritized).
renice: adjust priority of a running process
If something is already running and hogging your CPU, you don’t need to kill it and restart. renice updates the niceness of a process by its PID, by user (UID), or by process group (GID).
The nice value scale: -20 to +19 explained
The full scale runs from -20 (highest priority, most CPU-hungry) to +19 (lowest priority, will yield to almost anything). Default niceness for any process you start is 0. Here’s the rule that trips everyone up: regular users can only raise niceness (make a process more polite). Lowering niceness — making something more aggressive — requires root.
How Linux Process Scheduling Actually Works
To use nice values intelligently, it helps to know what they actually do under the hood. This is the part most tutorials skip, and it’s where things get interesting.
The Completely Fair Scheduler (CFS)
Since kernel 2.6.23, Linux has used the Completely Fair Scheduler, written by Ingo Molnar to replace the old O(1) scheduler. As Molnar himself put it in the official Completely Fair Scheduler documentation:
“CFS basically models an ‘ideal, precise multitasking CPU’ on real hardware.” — Ingo Molnar, Creator of CFS
In other words, CFS pretends every runnable process gets exactly 1/N of the CPU at all times, then uses a clever bookkeeping trick to make that approximately true on real silicon.
How nice values translate to CPU time
That bookkeeping trick is called virtual runtime (vruntime). Every process accumulates vruntime as it runs, and CFS always picks the process with the lowest vruntime to run next. Nice values change how fast a process accumulates vruntime — a low nice value (high priority) accumulates vruntime more slowly, so it gets picked more often.
The practical takeaway: a process at nice -20 gets roughly 10x more CPU time than a process at nice +19 when both are competing. That’s the spread you’re working with. Also worth flagging — niceness controls CPU scheduling only. If your process is waiting on disk, the network, or a database lock, nice won’t help. Use ionice for I/O priority. We’ll cover that combo later.
How to Check Process Priority in Linux
Before you renice anything, you need to see what’s already running and at what priority. There are three tools I reach for, and they all show the same data with different ergonomics.
Using ps to view nice values
The ps command is my go-to for scripting and quick lookups:
ps axo pid,comm,nice,cls --sort=-nice
That sorts every process by nice value, descending, so the most polite (highest nice) processes show up first. The cls column shows the scheduling class — usually TS for normal processes.
Using top to sort by priority
If you want a live view, the top command shows two columns that matter here: NI (the nice value) and PR (the kernel priority, calculated as 20 + NI for normal processes). Hit N in top to sort by PID, or P to sort by CPU. To sort by nice, you can press F, pick NI, then enable sorting.
Using htop for visual priority management
For interactive work I almost always reach for the htop command. Press F6 to sort by NICE, and you get a color-coded view that makes outliers obvious. You can even renice a process from inside htop — select it and hit F7 to lower nice (more polite) or F8 to raise it (more aggressive, root only).
Don’t confuse NI with PRI. NI is what you set. PRI is what the kernel uses internally, and it’s mostly derived from NI for normal processes. If you only remember one — focus on NI.
How to Use the nice Command
Now for the actual command. The basic syntax is dead simple:
nice -n [value] [command]
Running a process at lower priority
This is the 99% use case. You’re running something that doesn’t need to finish quickly and you want it out of the way of more important work.
For backups (my favorite example, since this is the lesson that started this article):
nice -n 15 tar -czf backup.tar.gz /home
Or if you’re compiling something big and don’t want your editor to lag:
nice -n 10 make -j$(nproc)
Heads up — if you just type nice command with no -n, the default applied is +10, not 0. That trips a lot of people up. I’ve seen folks add nice in front of a script “for safety” and then wonder why it’s slower than expected.
Running a process at higher priority (requires root)
To go negative, you need sudo. For something like a database that genuinely needs CPU priority on a shared box:
sudo nice -n -10 mysqld
I wrap a lot of these in tiny bash scripts so I don’t have to remember the exact value, especially for jobs I run from cron jobs. Wrapping nice in a script makes it self-documenting and easy to tweak later.
How to Use the renice Command
The whole reason renice exists is for moments when something is already running and chewing through your CPU. Maybe it’s a script you forgot about. Maybe it’s a backup that started 30 minutes early. Either way, you want to throttle it without interrupting it.
Renice a process by PID
renice -n 10 -p 3842
That sets PID 3842 to nice value +10 immediately. If you don’t know the PID, find it with:
pgrep firefox
ps aux | grep rsync
Renice all processes for a user
One of the most underused features. If a user on a shared box is generating tons of background load, you can renice everything they own in one shot:
sudo renice -n 5 -u alexa
Renice a process group by GID
sudo renice -n 10 -g 1234
Same logic — but applied to a process group. Useful when you’ve spawned a tree of workers under one parent.
And if reprioritizing a process isn’t enough — sometimes the right call is to kill a process in Linux entirely. Renice is for “play nice.” Kill is for “you’re done.”
Going Further: nice + ionice for Disk-Heavy Jobs
Here’s the trick I promised earlier and the single biggest upgrade you can make to your background scripts. Most “background” jobs aren’t CPU-bound — they’re disk-bound. Backups, big tar archives, rsync runs, video transcodes. For those, nice alone isn’t enough. You need ionice too.
ionice -c 3 nice -n 19 rsync -av /data /backup
Breaking it down: ionice -c 3 sets the I/O scheduling class to idle, meaning rsync only gets disk time when nothing else wants it. nice -n 19 caps the CPU side. Combined, this is about as polite as a process can get on Linux. It’s the gold standard for production background tasks, and it’s exactly what would have saved me from the homelab disaster I opened with.
Setting Process Priority in systemd Services
Manually nicing things is fine for one-offs. For services that run forever, bake the priority into the unit file. Pair this knowledge with systemctl for managing service state.
[Service]
ExecStart=/usr/local/bin/my-backup.sh
Nice=15
IOSchedulingClass=idle
CPUWeight=20
CPUQuota=25%
What each directive does:
- Nice= Sets niceness for the service. Same scale as the CLI: -20 to +19.
- IOSchedulingClass=idle Equivalent to
ionice -c 3. - CPUWeight= Relative CPU fairness. Replaces the deprecated
CPUShares=. - CPUQuota= Hard ceiling.
25%means the service literally cannot use more than a quarter of one CPU core.
For scheduled jobs, systemd timers can include all the same directives in their service unit, which is one big reason I’ve moved most of my cron jobs to timers.
Quick Reference: nice vs renice
| Aspect | nice | renice |
|---|---|---|
| When to use | Launching a new process | Adjusting a running process |
| Syntax | nice -n VAL CMD |
renice -n VAL -p PID |
| Target | Command to run | PID, UID (-u), or GID (-g) |
| Negative values | Root only | Root only |
And a cheat sheet for picking nice values in the wild:
- 0 — Default. Don’t touch unless you have a reason.
- 1–9 — Slightly backgrounded tasks. Compiles, log processing.
- 10–14 — Standard background work. Backups during business hours.
- 15–19 — Idle-grade tasks. Long rsync, video transcodes, large data moves.
- Negative — Critical real-time-ish services. Database servers, sometimes audio.
Reference the official nice man page when you want the authoritative word on flags and edge cases.
Common Mistakes and Gotchas
Watch out for these
I’ve personally tripped over every one of these at some point. Save yourself a 2 AM debugging session.
nice doesn’t help I/O-bound processes
If a process is stuck waiting on the disk, raising its nice value does nothing. Use vmstat or iostat first to see if you’re CPU-bound or I/O-bound. CPU-bound? Reach for nice. I/O-bound? You need ionice (or both).
Non-root users can’t go negative
You’ll see “permission denied” if you try. Even on your own processes. This is intentional — letting users escalate priority would let them starve other users.
nice doesn’t persist across restarts
If you renice a process and then the service restarts, you’re back to default. Bake niceness into the systemd unit if you want it to stick.
Child processes inherit parent niceness
This bit me once when a parent build script was renice’d to +15 and all its compile workers also crawled. Sometimes that’s what you want. Sometimes it isn’t. Just be aware.
Always check load and CPU first
Before you go reniceing things in a panic, take a breath and check load average and check CPU usage in Linux. The bottleneck is often somewhere else entirely.
Wrapping Up: Be Polite, Save Your Server
Once you internalize nice and renice, you stop seeing background jobs as risks and start seeing them as predictable, well-behaved citizens of your server. The mental model is simple: anything that doesn’t need to finish fast should run nice. Anything I/O-heavy should also run ionice. Anything persistent should set both in its systemd unit.
If you want to take this further, I’d suggest reading my guides on the htop command for live monitoring, or browsing the best Linux monitoring tools roundup if you want a complete observability stack so you can actually see what nice values are doing in production.
And the next time you set up a 2 AM backup job? Wrap it in ionice -c 3 nice -n 19. Future you, sipping morning coffee while the site stays up, will thank present you. That’s the lesson my homelab rsync taught me — and now it’s yours.




