Jak przywrócić wszystkie wątki (i dzieci) jednego procesu w systemie Linux?

22

Linux nie (jeszcze) postępuje zgodnie ze standardem POSIX.1, który mówi, że a renicena proces wpływa na „wszystkie wątki o zasięgu systemowym w tym procesie”, ponieważ zgodnie z dokumentacją pthreads (7) „wątki nie mają wspólnej dobrej wartości”.

Czasami jednak wygodne może być renice„wszystko” związane z danym procesem (jednym z przykładów byłyby procesy potomne Apache i wszystkie ich wątki). Więc,

  • jak mogę renicewszystkie wątki należące do danego procesu?
  • jak mogę renicewszystkie procesy potomne należące do danego procesu?

Szukam dość łatwego rozwiązania.

Wiem, że grupy procesów mogą czasem być pomocne, jednak nie zawsze pasują do tego, co chcę zrobić: mogą obejmować szerszy lub inny zestaw procesów.

Korzystanie z cgroupzarządzanego przez systemdmoże również być pomocne, ale nawet jeśli chcę o tym usłyszeć, najczęściej szukam „standardowego” rozwiązania.

EDYCJA: również man (7) pthreadsmówi „wszystkie wątki w procesie są umieszczone w tej samej grupie wątków; wszyscy członkowie grupy wątków mają ten sam PID”. Czy w ogóle możliwe jest renicecoś, co nie ma własnego PID?

Totor
źródło

Odpowiedzi:

19

Możesz użyć, /proc/$PID/taskaby znaleźć wszystkie wątki danego procesu, dlatego możesz użyć

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

do renicewszystkich wątków należących do danego procesu.

W ten sam sposób /proc/$PID/task/$PID/childrenmożna znaleźć wszystkie procesy potomne (lub /proc/$PID/task/*/childrenjeśli chcesz wszystkie procesy potomne wszystkich wątków danego procesu).

$ cat /proc/$PID/task/$PID/children | xargs renice $PRIO
$ cat /proc/$PID/task/*/children | xargs renice $PRIO
Anton Leontiev
źródło
man (7) pthreadsmówi o bieżącej implementacji (NPTL): „wszystkie wątki w procesie są umieszczone w tej samej grupie wątków; wszyscy członkowie grupy wątków mają ten sam PID” i „Wątki nie mają wspólnej dobrej wartości”. Jak w takim razie zrestartować wątek, który nie ma własnego PID, kiedy reniceużywa do tego PID?
Totor,
Próbowałem renice na identyfikator wątku, i to zgłasza 24995 (process ID) old priority 0, new priority -10. 24995 nie pojawia się ps, więc nie jest to proces. Może wątki odnawiające rzeczywiście działają?
Stefan Reich
9

Dobra wartość czy udziały w CPU?

Należy pamiętać, że w dzisiejszych czasach ładne wartości mogą nie być tak istotne w całym systemie, ze względu na automatyczne grupowanie zadań, szczególnie podczas korzystania z systemd . Więcej informacji można znaleźć w tej odpowiedzi .

Różnica między wątkami i procesami

Ważne pytanie w systemie Linux, ponieważ dokumentacja utrwala wątpliwości (na przykład wątki nieposiadające własnego PID).

Uwaga: ta odpowiedź dokładnie wyjaśnia wątki systemu Linux.

W skrócie: jądro obsługuje tylko „elementy uruchamialne”, to znaczy coś, co można uruchomić i zaplanować . Jeśli chodzi o jądro, te byty nazywane są procesami. Wątek jest rodzajem procesu, który dzieli (przynajmniej) przestrzeń pamięci i procedury obsługi sygnałów z innym.

Każdy taki proces ma unikalny w całym systemie identyfikator: PID (identyfikator procesu). W przypadku tak zwanych wątków jest czasami nazywany TID (identyfikator wątku), ale z punktu widzenia sysadmin (i jądra!) TID i PID są tym samym (dzielą tę samą przestrzeń nazw).

W rezultacie możesz renice każdy „wątek” osobno, ponieważ ma swój własny PID 1 .

Znajdowanie wszystkich PID-ów renice rekurencyjnie

Musimy uzyskać PID wszystkich procesów („normalnych” lub „wątków”), które są potomkami (dzieci lub w grupie wątków) procesu, który ma być poprawiony. Powinno to być rekurencyjne (biorąc pod uwagę dzieci dzieci).

Odpowiedź Antona Leontiewa daje podpowiedź: wszystkie nazwy folderów /proc/$PID/task/to PID wątków zawierający childrenplik z listą potencjalnych procesów potomnych.

Jednak brakuje mu rekurencyjności, więc oto szybki i brudny skrypt powłoki, aby je znaleźć:

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

Jeśli proces PID 1234 jest tym, który chcesz rekurencyjnie miły, teraz możesz:

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

1 Zauważ, że dla zgodności z POSIX, wywołanie getpid(2)w wątku nie da ci ogólnosystemowego unikalnego ID (PID) tego uruchamialnego bytu, ale raczej PID głównego procesu w „grupie wątków”. Zamiast tego musisz zadzwonić gettid(2). Zobacz tę odpowiedź, aby uzyskać więcej informacji.

Totor
źródło
6

Nie powinniśmy mylić PID procesu i identyfikatora wątku zapisanego TID lub komendy ps LPW. sPolecenie ma opcje do wyświetlania wątków i pod toplub htopprzełączać pomiędzy wątkami i procesu przez Hliście. Jak wcześniej powiedział @Totor, z NPTL, która jest bieżącą implementacją z jądrem> 2.6, wszystkie wątki mają ten sam pid, ale mają wyraźny tid. Wyświetlane są wszystkie wątki procesu według:

$ ps -Ljf <pid>

Te tid są nazwami katalogów pod /proc/<pid>/taski nawet jeśli renice (1) mówi, że domyślnym argumentem jest pid po zastosowaniu do pid, to renice tylko główny wątek (jest to błąd w implementacji linuxa napisany w setpriority (2) ) ), można go również zastosować do przyprawy i ponownie nićmi nitkę. Właśnie dlatego odpowiedź @Anton jest ważna.

Ale najczęściej istnieje łatwiejszy sposób na osiągnięcie pożądanego rezultatu, wszystkie te wątki mają ten sam pgid, który jest pid lidera grupy; możesz ponownie zareagować pgid, wydając:

$ renice -g <pgid>

Jeśli nie chcesz ponownie uruchamiać innego procesu zależnego od tego samego lidera grupy, musisz użyć przepisu @ Antona:

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

lub:

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

Możesz także chcieć dowiedzieć się, jakie są inne procesy w tej samej grupie niż proces, który chcesz ponownie uruchomić, to znaczy procesy, które współużytkują mają ten sam pgid. Możesz użyć ps (1) , psnie pozwala wybrać procesów według lidera grupy, ale możesz to zrobić grep a ps. Procesy z pgid 1908zostaną podane przez polecenie:

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

lub jeśli wolisz awk niż sed:

$ ps --no-header axo pid,pgid|awk '{if ($2=="1908") print $1;}'
marcz
źródło
To wydaje się nie działać poprawnie w 4.19.4 (Debian Stretch na razie): $ renice -n 18 -g 8524 renice: failed to get priority for 8524 (process group ID): No such process $ ps --no-header axo pid,pgid|awk '{if ($2=="8524") print $1;}' Podczas gdy metoda Totora działa / nadal działa: $ /bin/ls /proc/8524/task | /usr/bin/xargs renice 19 2739 (process ID) old priority 19, new priority 19 2740 (process ID) old priority 19, new priority 19 ... Potwierdziłem za pomocą / proc, htop, pstree itp., Że mam poprawne top- poziom PID. Może coś się zmieniło w ciągu ostatniego roku.
Bill McGonigle
Nie wiem, jak zrobiłeś test @ bill-mcgonigle, właśnie próbowałem z trzema jądrami 4.9.0 na Debian Stretch; 4.18.0 i 4.19.0 dotyczące testowania Debiana; I działa, jak powiedziałem powyżej.
marcz
Tak jak powiedziałem, Debian Stretch na 4.19.4 z pokazanymi poleceniami i danymi wyjściowymi; różnica wydaje się wynosić 4.19.0 w porównaniu z 4.19.4, ale jestem zaskoczony, że między tak małymi wersjami nastąpiłaby duża zmiana.
Bill McGonigle
Myślę, że twój proces 8524 jest PID wszystkich wątków procesu TID lub LPW, ale nie grupy procesów, więc oczywiście znajdziesz wszystkie wątki, /proc/8524/taskale renice -gzawiodły. Kiedy patrzysz na drzewo procesów, jedna gałąź znajduje się w tej samej grupie procesów, a nie tylko jeden proces wątkowy. Spróbuj ponownie sprawdzić wynik ps -Ljf.
marcz
0

Chciałbym polecić użycie argumentu -g (grupy procesów) zamiast -p (identyfikatory procesów) podczas używania renice. Robi to samo bez bash-foo.

to znaczy

(sudo) renice -n <NEW_PRIORITY> -g <MAIN_PROCESS_ID>
użytkownik12042
źródło
Odpowiedź marcz już o tym wspomina.
Totor
-1

Oto mój skrypt:

pgrep -v <PROCESS_NAME> | sudo xargs renice <NEW_PRIORITY>
Antonio Petricca
źródło
1
To uruchamia renice na każdym procesie z wyjątkiem tego, który nazwiesz. Osobiście uważam to polecenie za niebezpieczne i nieodpowiednie.
Totor
Zastanawiam się, czy miał na myśli -w nie -v
Diablo-D3