How to renice all threads (and children) of one process on Linux?

You can use /proc/$PID/task to find all threads of a given process, therefore you can use

$ ls /proc/$PID/task | xargs renice $PRIO

to renice all threads belonging to a given process.

Same way /proc/$PID/task/$PID/children can be used to find all child processes (or /proc/$PID/task/*/children if you want all child processes of all threads of a given process).

$ cat /proc/$PID/task/$PID/children | xargs renice $PRIO
$ cat /proc/$PID/task/*/children | xargs renice $PRIO

Finding all PIDs to renice recursively

We need to get the PIDs of all processes ("normal" or "thread") which are descendant (children or in the thread group) of the to-be-niced process. This ought to be recursive (considering children's children).

Anton Leontiev answer's gives the hint to do so: all folder names in /proc/$PID/task/ are threads' PID containing a children file listing potential children processes.

However, it lacks recursivity, so here is a quick & dirty shell script to find them:

#!/bin/sh
[ "$#" -eq 1 -a -d "/proc/$1/task" ] || exit 1

PID_LIST=
findpids() {
        for pid in /proc/$1/task/* ; do
                pid="$(basename "$pid")"
                PID_LIST="$PID_LIST$pid "
                for cpid in $(cat /proc/$1/task/$pid/children) ; do
                        findpids $cpid
                done
        done
}

findpids $1
echo $PID_LIST

If process PID 1234 is the one you want to recursively nice, now you can do:

renice -n 15 -p $(/path/to/findchildren.sh 1234)

Side notes

Nice value or CPU shares ?

Please note that nowadays, nice values may not be so relevant "system-wide", because of automatic task grouping, espacially when using systemd. Please see this answer for more details.

Difference between threads and processes

Note: this answer explains Linux threads precisely.

In short: the kernel only handles "runnable entities", that is, something which can be run and scheduled. Kernel wise, these entities are called processes. A thread, is just a kind of process that shares (at least) memory space and signal handlers with another one. Every such process has a system-wide unique identifier: the PID (Process ID).

As a result, you can renice each "thread" individually because they have their own PID1.


1 See this answer for more information about PID (ProcessID) and TID difference (ThreadID).


We should not confuse the process PID and the thread id sometime written TID or in the ps command LPW. The scommand has options to display threads, and under top or htop you switch between threads and process by the H letter. As previously told by @Totor, with NPTL, which is the current implementation with kernel > 2.6, all threads have the same pid, but they have a distinct tid. You show all the threads of a process by:

$ ps -Ljf <pid>

These tid are the names of the directories under /proc/<pid>/task, and even if renice(1) say that its default argument is a pid when applied to a pid it renice only the main thread (this is a bug in linux implementation as written in setpriority(2)), it can also be applied to a tid and it renices the thread. Thats why the answer of @Anton is valid.

But most often there is an easier way to achieve the desired result, all these threads share the same pgid which is the pid of the group leader; you can renice by pgid by issuing:

$ renice -g <pgid>

If you don't want to renice some other process that depends of the same group leader, you have to use the @Anton's recipe:

$ renice <priority> $(ls -1 /proc/<pid>/task)

or:

$renice <priority> $(ps --no-header -Lo tid <pid>)

You may also want to know what are the other processes of the same group than the process you want to renice, that is the processes which share has the same pgid. You can use ps(1), ps does not allow to select processes by group leader, but you can grep a ps to do it. The processes with pgid 1908 will be given by the command:

$ ps --no-header axo pid,pgid |sed -n '/^ *[0-9][0-9]*  *1908/s/[0-9][0-9]* *$//p'

or if you prefer awk to sed:

$ ps --no-header axo pid,pgid|awk '{if ($2=="1908") print $1;}'