Может ли ps отображать только неядерные процессы в Linux?

Ответы:

37

Это должно сделать (под Linux):

ps --ppid 2 -p 2 --deselect

kthreadd(PID 2) имеет PPID 0 ( в Linux 2.6+ ), но psне позволяет фильтровать PPID 0; таким образом это обходной путь.

Хауке Лагинг
источник
Хорошо, но насколько гарантировано, что kthreaddвсегда PID 2?
10
@ l0b0 Понятия не имею :-) Вы можете сделать это в два этапа: определить PID kthreadd, а затем построить соответствующий psвызов. Насколько гарантировано, что эта вещь будет «всегда» называться «kthreadd»? Безопасное решение было бы более сложным, работало бы psнормально и анализировало выходные данные, возможно, сделайте несколько тестов.
Хауке Лэнг
2
В Linux 2.4 на платформе x86, по крайней мере, эти процессы имели ppid 1, поэтому их нельзя было отличить таким образом.
Стефан Шазелас
1
быть похожим на "ps -ef" do "ps --ppid 2 -p 2 --deselect -f" и делать это как "ps aux" do "ps --ppid 2 -p 2 --deselect u"
Питер
1
@Totor Я проверил и похоже, что это xфлаг, который не работает с этим. ps au --ppid 2 -p 2 --deselectработает нормально.
Sankalp
9

Один из способов распознать процессы ядра - это то, что они не используют какую-либо пользовательскую память, поэтому поле vsz равно 0. Это также ловит зомби (спасибо Стефану Чазеласу за это наблюдение), которые могут быть удалены в зависимости от их статуса.

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

Чтобы перечислить только PID:

ps -e -o pid= -o state= -o vsize= | awk '$2 != "Z" && $3 != 0 {print $1}'
Жиль "ТАК - перестань быть злым"
источник
Как и мое решение, оно также будет включать процессы зомби.
Стефан Шазелас
1
@ StephaneChazelas Хорошая мысль, я добавил условие в фильтр.
Жиль "ТАК - перестань быть злым"
9

На практике я нашел следующую идиому:

ps auxf | grep -v ]$

Он фильтрует строки, заканчивающиеся скобками, что может привести к пропуску нежелательных записей, но это очень маловероятно. В обмен на это довольно легко запомнить и относительно быстро набрать.

Некоторые процессы, такие как avahi-daemon, добавляют к своим именам процессов информацию в скобках (имя хоста в случае avahi-daemon) и будут отфильтрованы этой командой.

onetom
источник
8

Одна из особенностей этих процессов заключается в том, что они не поддерживаются исполняемым файлом, так что вы можете сделать ( в zsh ):

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

Или с любой оболочкой POSIX:

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

Это проверка процессов, чья /proc/<pid>/exeссылка на файл.

Но это означает, что вы должны быть суперпользователем, чтобы иметь возможность проверять состояние /proc/<pid>/exeсимволической ссылки.

Изменить : Как это происходит, процессы зомби (по крайней мере) удовлетворяют тому же условию, поэтому, если вы не хотите, чтобы они были исключены, вам придется добавить их обратно. Подобно:

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

Обратите внимание, что ps -fимена этих процессов отображаются в квадратных скобках не потому, что они являются процессами ядра, а потому, что они имеют пустое значение argv[](поэтому ps показывает имя процесса вместо argv[0]этого). У вас также может быть процесс в пространстве пользователя с пустым, argv[]а у вас может быть имя процесса с argv[0]формой, [some-string]поэтому фильтрация psвывода на основе этих квадратных скобок не является надежной опцией.

Стефан Шазелас
источник
Я считаю, что это нестандартный синтаксис оболочки.
Тотор
1
@Totor, как я уже сказал, первый - это zshсинтаксис. Второй - это стандартный синтаксис POSIX sh(и, psи, findи, cutи paste). Конечно, /procэто не указано в POSIX.
Стефан Шазелас
Принятие этого ответа, потому что он универсален (спасибо за редактирование). Тем не менее, ответ Hauke ​​Laging также довольно приятный и прямой, если вы не имеете дело с ядром 2.4.
Тотор
@Totor, ответ Хауке также имеет то преимущество, что не требует привилегий суперпользователя. Мой ответ работает с ядрами 2.4 и 2.6 / 3, но я полагаю, что в любом случае он не будет работать в 4.x.
Стефан Шазелас
Хм, вы правы, я не думал о привилегиях суперпользователя. Это может привести к ошибкам, так как вы все равно получите ответ, когда вы не root, но он другой (поэтому вы должны быть осторожны, считая их, скажем wc -l). Ну, тогда я приму ответ Хауке Лагинга и дам вам голос. ;)
Тотор
1

Вы также можете просто проанализировать psвывод и найти имена процессов, которые не заключены в квадратные скобки:

ps aux | awk '$NF!~/^\[.+\]$/'
Тердон
источник
Немного менее ненадежный способ получить список пользователей, которые вас интересуют: awk -F: '$7 ~ home { print $1 }' /etc/passwd- но вы все равно получите процессы, которые упоминают любое такое имя пользователя, и оставите временный файл без дела. Я отзову свое отрицательное голосование, но только потому, что ваше третье решение разумно.
Кит Томпсон
Бах, ты прав до конца, @KeithThompson, удалил остальных, они того не стоят. Не могли бы вы помочь мне убрать (сейчас) устаревшие комментарии?
Terdon
2
Обратите внимание, что $NFэто последнее слово командной строки в ps auxвыводе. Неядерные процессы могут быть [...]там. Как я сказал в своем ответе, [xxx]нотация не потому, что они являются процессами ядра, а потому, что у них нет командной строки (без аргументов), которая также допускается для процессов, не связанных с ядром.
Стефан Шазелас
1

Для любого, кто пробует это в busybox, где psсильно упрощено и вывод отличается, этот вариант отличного ответа Жиля хорошо работает:

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

Согласно ответу Жиля, методология здесь состоит в том, чтобы найти процессы, которые не используют пользовательскую память (`vsz col == 0), и отфильтровать процессы зомби (статус col не равен 'Z').

Выходные столбцы могут быть легко отрегулированы при условии, что номера полей awk на основе 1 настроены соответствующим образом. Посмотрите варианты, которые ваш ps имеет, введя фиктивное значение, и оно сообщит вам. Например:

$ ps -o foo
ps: bad -o argument 'foo', supported arguments: user,group,comm,args,pid,ppid,pgid,tty,vsz,stat,rss
Russ
источник
0

Если вам нужны только подсчеты ... У меня была аналогичная необходимость фильтровать ядро ​​и пользовательские процессы, но мне нужны были только соответствующие подсчеты для каждого. Это было мое решение:

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]}'

Образец вывода :

Kernel processes    353
User processes       52
Total processes     405

Объяснение : Я использую хак, что процессы VSZ = 0 можно считать процессами ядра. Итак awk, я оцениваю сравнение VSZ (с ps -eo vsize), равно ли оно нулю. Результатом сравнения будет либо логическое значение 0, либо 1. Я создаю массив p[], и, когда я запускаю список процессов, если это процесс ядра, я увеличиваю его p[1]++. В противном случае, как пользовательский процесс, я увеличиваю p[0]++. После всех приращений я помечаю и печатаю значения (то есть подсчитывает) для p [0] и p [1] в END { }блоке.

Джошуа Хубер
источник
0

То, что вы ищете, друг мой, нет ps, но pstree.

Сначала определите первый процесс ядра. Его PID обычно равен 1 в системе без systemd и 2 в systemd.

Затем используйте эту команду:

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

Выбранный ответ (один с ✅) использует другую команду:

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

Проблема этой psкоманды в том, что она включает в себя только прямых потомков, но не всех потомков. Команда pstreeвключает в себя всех потомков. Вы можете сравнить и посчитать вывод этих двух команд (простой способ использования | wc) для проверки.

ssppjj
источник
0

Я создал скрипт psa для этой цели. Обратите внимание, что это зависит от инструмента linechop .

Томаш Поспишек
источник