Skip to content

103.6 Modify process execution priorities

Weight: 2

Candidates should be able to manage process execution priorities.

Objectives

  • Know the default priority of a job that is created.
  • Run a program with higher or lower priority than the default.
  • Change the priority of a running process.

Terms

nice, ps, renice, top

On a Linux machine, you might have hundreds of processes running at the same time and competing for more CPU and RAM. The good news is that you can give some of the processes higher or lower priority, or nice-ness, in this competition. Let's have a look at a sample top output:

$ top

Tasks: 169 total,   1 running, 168 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.0 us,  3.0 sy,  0.0 ni, 97.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   5948.9 total,   4115.2 free,    438.2 used,   1395.5 buff/cache
MiB Swap:    975.0 total,    975.0 free,      0.0 used.   5210.3 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND  
   6496 nagato    20   0   10112   3704   3212 R   6.2   0.1   0:00.01 top  
      1 root      20   0  165172  10576   7780 S   0.0   0.2   0:02.80 systemd  
      2 root      20   0       0      0      0 S   0.0   0.0   0:00.09 kthreadd  
      3 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_gp  
      4 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 rcu_par_gp  
      6 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 kworker/0:0H-events_highpri  
      8 root       0 -20       0      0      0 I   0.0   0.0   0:12.71 kworker/0:1H-events_highpri  
      9 root       0 -20       0      0      0 I   0.0   0.0   0:00.00 mm_percpu_wq  
     10 root      20   0       0      0      0 S   0.0   0.0   0:00.00 rcu_tasks_rude_  
     11 root      20   0       0      0      0 S   0.0   0.0   0:00.00 rcu_tasks_trace

The NI column shows how nice this process is. The nicer the process, the less CPU it asks for. The nice values can be from -20 to 19. To interpret this value, look at it like this: a process with nice = -20 is ANGRY and gets more priority for CPU and RAM, while a process with nice = 19 is SUPER NICE and lets other processes use the resources before it.

Look at the two columns together in that output. Most processes show PR 20 NI 0. The kernel workers show PR 0 NI -20, which is the angry end of the scale. Those are jobs the kernel wants handled immediately.

The scale, drawn out:

   -20 ................ 0 ................ 19
    |                   |                   |
  angry             the default          super nice
  takes CPU                            gives CPU away
  first                                to everyone else

  only root can go below 0

Why the scheduler needs this at all: only one process can hold the CPU at a time. Linux is preemptive, which means the kernel can take the CPU away from a running process and hand it to a more important one, even if that process did not ask to give it up. The scheduler decides who goes next, and the nice value is one of the inputs to that decision.

Scheduling comes in two kinds. Real-time processes are scheduled strictly by priority and always outrank normal ones. Normal processes are everything else, including all your programs, and those are the only ones the nice value affects.

Underneath the nice value there is a second number, the static priority. Linux reserves priorities 0 to 99 for real-time processes and 100 to 139 for normal ones. Lower means more important. You can read it straight from /proc:

$ grep ^prio /proc/1/sched
prio : 120

PID 1 is systemd, and 120 is the standard priority for a normal process. That is why the range around it runs from 100 to 139.

The confusing part is that ps and top each display this number differently:

   real value in /proc/PID/sched     120
   ps -el PRI column                  80     (add 40 to get 120)
   top PR column                      20     (0 to 39 range)

ps shows priorities from -40 to 99 for historical reasons, so add 40 to get the real number. top shifts real-time priorities into negative numbers, or shows rt, which makes them easy to spot at a glance.

The default value for nice is normally set to 0. This can be checked with:

$ nice
0

You can also check the nice-ness using the ps command:

$ ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1000 15044 15035  0  80   0 -  7453 wait   pts/29   00:00:00 bash
0 S  1000 15052 15044  0  60 -20 -  3976 hrtime pts/29   00:00:00 sleep
0 R  1000 15080 15044  0  80   0 -  4680 -      pts/29   00:00:00 ps

Compare the PRI and NI columns on the middle line. That sleep has NI -20 and PRI 60, while the normal processes have NI 0 and PRI 80. Lowering the nice value by 20 lowered the priority number by 20 as well. The two move together, which is what "nice affects priority" means in practice.

Two more ways to list priorities. ps -Al or ps -el shows every process on the system:

$ ps -el
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 1 0 0 80 0 - 9292 - ? 00:00:00 systemd
4 S 0 19 1 0 80 0 - 8817 - ? 00:00:00 systemd-journal
4 S 104 61 1 0 80 0 - 64097 - ? 00:00:00 rsyslogd
4 S 0 63 1 0 80 0 - 7244 - ? 00:00:00 cron
1 S 0 126 1 0 80 0 - 4031 - ? 00:00:00 dhclient
4 S 0 154 1 0 80 0 - 3937 - pts/0 00:00:00 agetty
4 S 0 160 1 0 80 0 - 16377 - ? 00:00:00 sshd
4 S 0 280 0 0 80 0 - 5301 - ? 00:00:00 bash
0 R 0 392 280 0 80 0 - 7221 - ? 00:00:00 ps

And you can pick your own columns, which is useful for finding the heaviest processes:

$ ps -e -o user,uid,comm,tty,pid,ppid,pri,pmem,pcpu --sort=-pcpu | head

Reading that: -o chooses the columns, --sort=-pcpu sorts by CPU percentage descending, and head keeps only the top ten.

Setting nice-ness

If you need to change the niceness level of a program you can run it with the nice command and the -n switch (for nice):

$ nice -n 19 echo "I am running!"
I am running!
$ nice -n -20 echo "I am running!"
nice: cannot set niceness: Permission denied
I am running!
$ sudo nice -n -20 echo "I am running!"
I am running!

As you can see in the above example, only root can issue high-priority niceness, below 0.

Look closely at the second command. It printed an error and still ran. nice could not set the priority, so it gave up on that part and ran the command at the normal priority anyway. It did not refuse the whole job.

If you run a command with nice without -n, the default will be -n 10.

$ nice xeyes &
[1] 15217
$ ps -l
F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S  1000 15044 15035  0  80   0 -  7455 wait   pts/29   00:00:00 bash
0 S  1000 15217 15044  0  90  10 - 12522 poll_s pts/29   00:00:00 xeyes
0 R  1000 15218 15044  0  80   0 -  4680 -      pts/29   00:00:00 ps

That proves the default. xeyes was started with plain nice and no number, and it shows NI 10, with PRI raised from 80 to 90 to match.

The rule about who may do what is worth stating plainly, because it is easy to get backwards:

   normal user   can only RAISE the nice value    0 -> 19
                 (make a process nicer, lower priority)
                 and cannot lower it again afterwards

   root          can set anything                -20 -> 19

A normal user lowering priority is safe, since it only gives resources away. Raising priority takes resources from everyone else, which is why it needs root.

Real world use for nice -n 19: running a big backup or compression job on a busy server:

$ nice -n 15 tar czf home_backup.tar.gz /home

The archive still gets made, but it steps aside whenever anything else needs the CPU, so users do not notice the server slowing down.

Changing priorities

The renice command can be used to change the niceness of your running processes, or others if you are root:

$ ps -ef | grep firefox
nagato   13605 11226 30 08:28 ?        00:10:13 /usr/lib/firefox/firefox
nagato   15192 15044  0 09:01 pts/29   00:00:00 grep firefox
$ sudo renice -n -10 13605
13605 (process ID) old priority 5, new priority -10

You can also press r in the top command to renice a process.

Note the two step pattern there. ps -ef | grep first, to find the PID, then renice on that number. renice works on a running process, so it always needs a PID, a group or a user, never a command name.

The -p form gives the same output message:

# renice -10 -p 2164
2164 (process ID) old priority 0, new priority -10

Two more options change many processes at once:

  • -g applies to every process owned by a group
  • -u applies to every process owned by a user

So renice +5 -g users raises the nice value of every process belonging to the users group by five.

Real world use for renice -u: a shared build server where one developer's jobs are starving everyone else. renice +10 -u bob pushes all of that user's processes down in one command, without having to hunt for each PID.

The top route: press r on the main screen and it asks which process:

PID to renice [default pid = 1]

Type the PID and press Enter, then it asks for the new value with Renice PID 1 to value. This is the same job as renice, done inside the live display.

Summary

I have a Linux system where far more processes exist than there are CPUs, so the kernel's scheduler decides who runs next. Linux is preemptive, which means it can take the CPU away from a running process and hand it to a more important one without waiting to be asked. Most of my programs run under the normal scheduling policy, and those are the ones I can influence.

The number I actually change is the nice value. It runs from -20 to 19, and the default for every new process is 0. A low number means the process is demanding and gets the CPU sooner, a high number means it is polite and lets others go first. Underneath that sits the static priority, which I can read as prio in /proc/PID/sched and which normally shows 120. Both ps and top display that same number differently, ps in the PRI column where I add 40 to get the real value, and top in the PR column where real-time processes appear as negative or as rt.

To start something at a different priority I use nice. With -n I pick the value, and without it the default is 10. To change something already running I use renice with a PID, or -g for a whole group and -u for a whole user. I can also do it live by pressing r inside top. Both ps -l and top show me the current NI column so I can check the result.

The permission rule is the part I have to keep straight. Any user can make their own process nicer by raising the number, but only root can lower it below zero, because lowering it takes CPU away from everything else on the machine. That is also why nice -n -20 as a normal user prints a permission error and then runs the command anyway at the normal priority, rather than refusing outright.