web-dev-qa-db-fra.com

Comment reniser toutes les discussions (et les enfants) d'un processus sur Linux?

Linux ne suive pas (encore) la norme POSIX.1 qui dit qu'un renice sur un processus affecte "tous les filets de portée du système dans le processus", car selon la = Pthreads (7) Doc "Les threads ne partagent pas une belle valeur commune".

Cependant, parfois, il peut être pratique pour renice "tout" lié à un processus donné (un exemple serait des processus enfants Apache et tous leurs discussions). Donc,

  • comment puis-je renice tout threads appartenant à un processus donné?
  • comment puis-je renice tout processus enfant ​​appartenant à un processus donné?

Je cherche une solution assez facile.

Je sais que Groupes de processus Peut parfois être utile, cependant, ils ne correspondent pas toujours à ce que je veux faire: ils peuvent inclure un ensemble de processus plus large ou différent.

L'utilisation d'un cgroup géré par systemd pourrait aussi être utile, mais même si je suis intéressé à en entendre parler, je cherche principalement une solution "standard".

EDIT: En outre, man (7) pthreads dit "Tous les fils d'un processus sont placés dans le même groupe thread; tous les membres d'un groupe de threads partagent le même PID". Alors, est-ce même possible à renice quelque chose qui n'a pas sa propre pid?

23
Totor

Bonne valeur ou actions de la CPU?

Veuillez noter que de nos jours, de belles valeurs peuvent ne pas être si pertinentes "système à l'échelle du système", en raison du groupe de tâches automatiques, espacialement lors de l'utilisation SystemD. S'il vous plaît voir cette réponse Pour plus de détails.

Différence entre les threads et les processus

Question importante sur Linux, car la documentation perpétue des doutes (sur les threads ne présentant pas leur propre PID par exemple).

Remarque: cette réponse explique précisément des threads Linux.

En bref: le noyau ne traite que des "entités runnables", c'est-à-dire quelque chose qui peut être exécuter et programmé. Bernel Sage, ces entités s'appellent des processus. Un thread, n'est qu'une sorte de processus qui partage (au moins) espace mémoire et des gestionnaires de signaux avec un autre.

Tous ces processus ont un identifiant unique à l'échelle du système: le PID (ID de processus). Pour les soi-disant threads, il est parfois appelé TID (ID de fil), mais à partir du point de vue Sysadmin (et du noyau!), Tid et PID sont la même chose (ils partagent la même espace de noms).

En conséquence, vous peut renice chaque "thread" individuellement, car ils ont leur PID1.

Trouver tous les PIDS à renice récursivement

Nous devons obtenir les PID de tous les processus ("normaux" ou "thread") qui sont descendants (enfants ou dans le groupe de fil) du processus à être soigné. Cela devrait être récursif (compte tenu des enfants des enfants).

Anton Leontiev Réponse's's's's's's's's's's's's's's's's's's's Pour le faire: Tous les noms de dossiers dans /proc/$PID/task/ Sont des threads 'PID contenant un children répertorie des processus potentiels pour enfants potentiels.

Cependant, il manque de récursivité, alors voici un script de shell rapide et sale pour les trouver:

#!/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

Si le processus PID 1234 est celui que vous voulez récursivement agréable, vous pouvez maintenant faire:

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

1 Notez que, pour la conformité de POSIX, appelez getpid(2) dans un thread sera non Donne-vous l'ID unique à l'échelle du système (PID) de cette entité annulable, mais plutôt du PID de le processus principal dans le "groupe de thread". Vous auriez besoin d'appeler gettid(2) à la place. Voir cette réponse pour plus d'informations.

10
Totor

Vous pouvez utiliser /proc/$PID/task Pour trouver tous les discussions d'un processus donné, vous pouvez donc utiliser

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

à renice tous threads appartenant à un processus donné.

De la même façon /proc/$PID/task/$PID/children peut être utilisé pour trouver tous processus enfants (ou /proc/$PID/task/*/children Si vous voulez tous processus enfant de tous -threads d'un processus donné).

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

Nous ne devrions pas confondre le processus PID et l'ID de thread de la TID ou dans la commande PS LPW. Le scommand a des options pour afficher des threads et sous top ou htop Vous basculez entre les threads et le processus par la lettre H. Comme indiqué précédemment par @totor, avec NPTL, qui est la mise en œuvre actuelle avec le noyau> 2.6, toutes les threads ont le même PID, mais ils ont une TID distincte. Vous montrez tous les discussions d'un processus par:

$ ps -Ljf <pid>

Ces enfants sont les noms des répertoires sous /proc/<pid>/task, et même si Renise (1) Dis dire que son argument par défaut est un PID lorsqu'il est appliqué à un PID, il ne s'agit que du fil principal (ceci est Un bogue dans la mise en oeuvre de Linux comme écrit dans SETPIRIORITY (2) ), il peut également être appliqué à un TID et il règne le fil. C'est pourquoi la réponse de @anton est valide.

Mais le plus souvent, il existe un moyen plus facile d'atteindre le résultat souhaité, tous ces threads partagent le même PGID qui est le PID du chef de groupe; Vous pouvez reniser par PGID en émettant:

$ renice -g <pgid>

Si vous ne voulez pas reniser un autre processus qui dépend du même chef de groupe, vous devez utiliser la recette de @ Anton:

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

ou:

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

Vous voudrez peut-être aussi savoir quels sont les autres processus du même groupe que le processus que vous souhaitez reniser, c'est-à-dire les processus qui partagent ont le même PGID. Vous pouvez utiliser PS (1) , ps _ ne permet pas de sélectionner des processus par leader du groupe, mais vous pouvez grep A ps pour le faire. Les processus avec pgid 1908 sera donné par la commande:

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

ou si vous préférez awk à sed:

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

Selon man renice (emphasis mine):

renice modifie la priorité de planification d'un ou de plusieurs processus de fonctionnement. Le premier argument est la valeur de priorité à utiliser. Les autres arguments sont interprétés comme ID de processus (par défaut), ID de groupe de processus, ID utilisateur ou noms d'utilisateur. (...)

Et en effet, man pgrep démontre, comme exemple:

Exemple 4: Faites tout chrome processus fonctionnant mieux:

$ renice +4 $(pgrep chrome)

Selon ceux-ci, vous pouvez combiner renice avec pgrep 's -w | --lightweight Switch to Renise Tous les threads à la fois, comme ça:

renice <priority> $(pgrep -w <process_name>)

Et à Renice Tous les processus enfants:

renice <priority> $(pgrep -P $(pgrep <process_name>))

Remarquez que vous pouvez également utiliser -f Commutateur avec pgrep Pour interroger non seulement le nom du processus, mais la ligne de commande complète (ne doit pas nécessairement être une correspondance complète).

0
Marc.2377

J'aimerais vous recommander d'utiliser l'argument -g (groupes de processus) au lieu de la -p (ID de processus) tout en utilisant RENICE. C'est la même chose sans Bash-foo.

c'est à dire.

(Sudo) renice -n <NEW_PRIORITY> -g <MAIN_PROCESS_ID>
0
user12042