Czy ps może wyświetlać w systemie Linux tylko procesy inne niż jądro?

Odpowiedzi:

37

Powinno to zrobić (w systemie Linux):

ps --ppid 2 -p 2 --deselect

kthreadd(PID 2) ma PPID 0 ( w Linuksie 2.6+ ), ale psnie pozwala na filtrowanie pod kątem PPID 0; więc to obejście.

Hauke ​​Laging
źródło
Fajnie, ale jak gwarantowane jest to, że kthreaddzawsze jest to PID 2?
l0b0
@ l0b0 Nie mam pojęcia :-) Możesz to zrobić w dwóch krokach: Określ PID kthreadd, a następnie zbuduj odpowiednie pswywołanie. Jak zagwarantowane jest, że to „zawsze” będzie nazywać się „kthreadd”? Bezpieczne rozwiązanie byłoby bardziej skomplikowane, działałoby psnormalnie i analizowałoby dane wyjściowe, może wykonałby jakieś testy.
Hauke ​​Laging
2
W Linuksie 2.4 na architekturze x86 procesy te miały ppid 1, więc nie można było tego tak odróżnić.
Stéphane Chazelas
1
być jak "ps -ef" zrobić "ps --ppid 2 -p 2 --deselect -f" i zrobić to jak "ps aux" zrobić "ps --ppid 2 -p 2 - deselect u"
Peter
1
@Totor Sprawdziłem i wygląda na to, że xflaga nie działa z tym. ps au --ppid 2 -p 2 --deselectdziała OK.
Sankalp,
9

Jednym ze sposobów rozpoznania procesów jądra jest to, że nie używają one żadnej pamięci użytkownika, więc pole vsz wynosi 0. To także łapie zombie (dzięki Stephane Chazelas za tę obserwację), które można wyeliminować na podstawie ich statusu.

ps axl | awk '$7 != 0 && $10 !~ "Z"'

Aby wyświetlić tylko PID:

ps -e -o pid= -o state= -o vsize= | awk '$2 != "Z" && $3 != 0 {print $1}'
Gilles „SO- przestań być zły”
źródło
Podobnie jak moje rozwiązanie obejmie również procesy zombie.
Stéphane Chazelas,
1
@StephaneChazelas Dobrze, dodałem warunek do filtra.
Gilles „SO- przestań być zły”
9

W praktyce znalazłem następujący idiom:

ps auxf | grep -v ]$

Filtruje linie kończące się nawiasami, co może skutkować pominięciem niepożądanych wpisów, ale jest to bardzo mało prawdopodobne. W zamian jest dość łatwy do zapamiętania i stosunkowo szybki do pisania.

Niektóre procesy, takie jak demon avahi, dodają do nawiasów informacje o nazwie procesu (nazwa hosta w przypadku demona avahi) i zostaną odfiltrowane przez to polecenie.

onetom
źródło
8

Jedną ze szczególnych cech tych procesów jest to, że nie są one wspierane przez plik wykonywalny, więc możesz zrobić ( w zsh ):

ps /proc/[0-9]*/exe(^-@:h:t)

Lub z dowolną powłoką POSIX:

ps -p "$(find -L /proc/[0-9]*/exe ! -type l | cut -d / -f3 | paste -sd , -)"

To jest sprawdzanie procesów, których /proc/<pid>/exelink do pliku.

Ale to oznacza, że ​​musisz być superużytkownikiem, aby móc sprawdzić stan /proc/<pid>/exedowiązania symbolicznego.

Edycja : Tak się składa, że ​​procesy zombie (przynajmniej) spełniają ten sam warunek, więc jeśli nie chcesz ich wykluczać, musisz je dodać z powrotem. Lubić:

ps -p "$(
  { find -L /proc/[0-9]*/exe ! -type l | cut -d / -f3
    ps -Ao pid=,state= | sed -n 's/ Z//p'
  } | paste -sd , -)"

Zauważ, że ps -fpokazuje te nazwy procesów w nawiasach kwadratowych nie dlatego, że są procesami jądra, ale ponieważ mają puste argv[](więc ps pokazuje nazwę procesu zamiast argv[0]tam). Można mieć proces przestrzeni użytkownika z pustym argv[]jak dobrze i można mieć nazwę procesu z argv[0]który jest w postaci [some-string]tak filtrowanie pswyjścia opartą na tych nawiasach kwadratowych nie jest opcją niezawodne.

Stéphane Chazelas
źródło
Sądzę, że to niestandardowa składnia powłoki.
Totor
1
@Totor, jak powiedziałem, pierwszy to zshskładnia. Drugi to standardowa składnia POSIX sh(i psoraz findi cuti paste). Oczywiście /procnie jest to określone przez POSIX.
Stéphane Chazelas,
Zaakceptowanie tej odpowiedzi, ponieważ jest uniwersalne (dzięki za edycję). Jednak odpowiedź Hauke ​​Laging jest również całkiem przyjemna i prosta, o ile nie radzisz sobie z jądrem 2.4.
Totor
@Totor, odpowiedź Hauke ​​ma tę zaletę, że nie wymaga przywileju administratora. Moja odpowiedź działa z jądrem 2.4 i 2.6 / 3, ale przypuszczam, że nie ma gwarancji, że i tak będzie działać w 4.x.
Stéphane Chazelas,
Hmm, masz rację, nie myślałem o przywilejach rootowania. Może to prowadzić do błędów, ponieważ nadal nie otrzymujesz odpowiedzi, gdy nie jesteś rootem, ale jest inaczej (więc powiedz, musisz być ostrożny, licząc je wc -l). Cóż, zaakceptuję odpowiedź Hauke ​​Laging i dam ci głos. ;)
Totor
1

Możesz także po prostu przeanalizować dane pswyjściowe i poszukać nazw procesów, które nie są w nawiasach:

ps aux | awk '$NF!~/^\[.+\]$/'
terdon
źródło
Nieco mniej zawodny sposób na uzyskanie listy użytkowników, którymi jesteś zainteresowany: awk -F: '$7 ~ home { print $1 }' /etc/passwd- ale nadal będziesz otrzymywać procesy, które wspominają taką nazwę użytkownika, i pozostawisz plik tymczasowy leżący w pobliżu. Wycofam moją opinię, ale tylko dlatego, że twoje trzecie rozwiązanie jest rozsądne.
Keith Thompson,
Bah, masz rację przez całą drogę, @KeithThompson, usunąłeś innych, nie są tego warci. Czy możesz mi pomóc oczyścić (teraz) przestarzałe komentarze?
terdon
2
Zauważ, że $NFjest to ostatnie słowo wiersza poleceń w ps auxdanych wyjściowych. Mogą [...]tam istnieć procesy inne niż jądro . Jak powiedziałem w mojej odpowiedzi [xxx]notacja nie dlatego, że są procesy jądra, ale ponieważ nie mają linii poleceń (bez argumentów), który jest również dozwolonych procesów non-jądra.
Stéphane Chazelas
1

Dla każdego, kto spróbuje tego w busyboksie, gdzie psjest bardzo uproszczony, a wyniki są inne, ten wariant świetnej odpowiedzi Gillesa działa dobrze:

ps -o pid,user,comm,vsz,stat | awk '$4 != 0 && $5 !~ "Z"'

Zgodnie z odpowiedzią Gillesa metodologia polega na tym, aby znaleźć procesy, które nie wykorzystują pamięci użytkownika (`vsz col == 0) i odfiltrować procesy zombie (status col nie jest 'Z').

Kolumny wyjściowe można łatwo regulować, o ile odpowiednio zmieniane są liczby pól awk oparte na 1. Zobacz opcje dostępne dla twojego ps, wprowadzając fałszywą wartość, a ci to powie. Na przykład:

$ ps -o foo
ps: bad -o argument 'foo', supported arguments: user,group,comm,args,pid,ppid,pgid,tty,vsz,stat,rss
Russ
źródło
0

Jeśli potrzebujesz tylko zliczeń ... Miałem podobną potrzebę filtrowania jądra względem procesów użytkownika, ale potrzebowałem tylko odpowiednich zliczeń każdego z nich. To było moje rozwiązanie:

ps -eo vsize | awk '{p[$1==0]++} END {printf "%-16s %6d\n%-16s %6d\n%-16s %6d\n", "Kernel processes", p[1], "User processes", p[0], "Total processes", p[0]+p[1]}'

Przykładowe dane wyjściowe :

Kernel processes    353
User processes       52
Total processes     405

Objaśnienie : Używam hacka, że ​​procesy VSZ = 0 można uznać za procesy jądra. Tak więc awk, oceniam porównanie na VSZ (od ps -eo vsize), czy jest równe zero. Wynikiem porównania będzie wartość logiczna 0 lub 1. Tworzę tablicę p[], a gdy przeglądam listę procesów, jeśli jest to proces jądra, zwiększam p[1]++. W przeciwnym razie, jako proces użytkownika, zwiększam p[0]++. Po wszystkich inkrementacjach oznaczam i drukuję wartości (tj. Liczby) dla p [0] i p [1] w END { }bloku.

Joshua Huber
źródło
0

Czego szukasz, przyjacielu, nie jest ps, ale pstree.

Najpierw zidentyfikuj pierwszy proces jądra. Jego PID to zwykle 1 w systemie bez systemd i 2 z systemd.

Następnie użyj tego polecenia:

$ pstree -p <1 or 2> | grep -o '([0-9]\+)' | grep -o '[0-9]\+'

Wybrana odpowiedź (jedna z ✅) używa innego polecenia:

$ ps --ppid 2 -p 2 --deselect

Problem z tym pspoleceniem polega na tym, że obejmuje on tylko bezpośrednie dzieci, ale nie wszystkich potomków. pstreePolecenie zawiera wszystkie elementy podrzędne. Możesz porównać i policzyć dane wyjściowe tych dwóch poleceń (używa się łatwego sposobu | wc) do weryfikacji.

ssppjj
źródło