Більш елегантний «ps aux | grep -v grep »


177

Коли я перевіряю перелік процесів і вичищаю цікаві для мене, grepсам результат також включається до результатів. Наприклад, для переліку терміналів:

$ ps aux  | grep terminal
user  2064  0.0  0.6 181452 26460 ?        Sl   Feb13   5:41 gnome-terminal --working-directory=..
user  2979  0.0  0.0   4192   796 pts/3    S+   11:07   0:00 grep --color=auto terminal

Зазвичай я користуюся ps aux | grep something | grep -v grep щоб позбутися останнього запису ... але це не елегантно :)

У вас є більш елегантний хак для вирішення цієї проблеми (крім загортання всієї команди в окремий сценарій, що також непогано)


4
Для чого це варто, це давній FAQ. Див. Пункт 3.10 за адресою faqs.org/faqs/unix-faq/faq/part3
триплея

1
Дякую за довідку. Ось їх метод:ps ux | awk '/name/ && !/awk/ {print $2}'
Якуб М.

Чим займається grep -v grepчастина?
Jwan622

2
@ Jwan622 grep -v grepвиключає grepрезультати grep. Якщо grep використовується в поєднанні з ps, то також буде показаний процес grep (з аргументами grep), що збільшить ваші результати. grep -v grep - поширений спосіб уникнути цього
Євген Платонов,

Відповіді:


282

Звичайна методика така:

ps aux | egrep '[t]erminal'

Це буде відповідати рядкам, що містять terminal, що egrep '[t]erminal'ні! Він також працює над багатьма ароматами Unix.


1
Це працює для мене для довільної рядки, але не для імені користувача, наприклад ps aux | grep '[r]oot'. Хтось знає, чому?
kxsong

2
@kxsong: | grep '[t]erminal'вибирає будь-який рядок, що містить слово "термінал", не додаючи слово "термінал" у список процесів. Чого ви намагаєтесь досягти | grep '[r]oot'і як це не працює? Ймовірно, буде краще рішення.
Johnsyweb

3
Виправте мене, якщо я помиляюся, але це також повинно працювати на будь-якій позиції зірваного символу: ps aux | grep "te [r] minal"
meso_2600

2
блискучий хак (я думаю, я повинен так назвати, оскільки автори aux / grep, мабуть, не думали про цей сценарій)
Michael Trouw

2
@JamieJag: Ну ... як я вже сказав у своєму дописі, grep '[t]erminal'відповідатимуть рядки, що містять terminal. Вихід з ps auxбуде мати рядок з grep '[t]erminal'(з квадратними дужками), який не містить рядка terminal(без того ж).
Johnsyweb

57

Використовуйте pgrep . Це надійніше.


pgrepне працюватиме , якщо я дивлюся, наприклад , дляps aux | grep 'ssh options'
Якуб М.

12
Якуб М.: А що pgrep -f?
Hillu

4
@ jakub-m За замовчуванням pgrepвідповідає лише шаблону проти імені процесу. Щоб відповідати всій команді, використовуйте -fпрапор.
bluecollarcoder

3
pgrepповертає лише ідентифікатори процесу.
Мелаб

1
старіші версії взяли pgrep -fl(але не вдалося побачити повний cmdline без -fвідповідності повного cmdline, деталі: serverfault.com/a/619788/44183 ). Але так, якщо вам потрібна будь-яка інша інформація, крім pid, cmdline, вам потрібна ps. Може поєднувати їх:ps -p $(pgrep -f foo)
Бені Чернявський-Паскін

29

Ця відповідь ґрунтується на попередній pgrep відповіді . Він також ґрунтується на іншій відповіді, що поєднує використання psз pgrep. Ось кілька відповідних навчальних прикладів:

$ pgrep -lf sshd
1902 sshd

$ pgrep -f sshd
1902

$ ps up $(pgrep -f sshd)
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      1902  0.0  0.1  82560  3580 ?        Ss   Oct20   0:00 /usr/sbin/sshd -D

$ ps up $(pgrep -f sshddd)
error: list of process IDs must follow p
[stderr output truncated]

$ ps up $(pgrep -f sshddd) 2>&-
[no output]

Вищезазначене може використовуватися як функція :

$ psgrep() { ps up $(pgrep -f $@) 2>&-; }

$ psgrep sshd
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      1902  0.0  0.1  82560  3580 ?        Ss   Oct20   0:00 /usr/sbin/sshd -D

Порівняйте з використанням psз grep. Корисний рядок заголовка не друкується:

$  ps aux | grep [s]shd
root      1902  0.0  0.1  82560  3580 ?        Ss   Oct20   0:00 /usr/sbin/sshd -D

Дивіться сторінку github.com/blueyed/oh-my-zsh/blob/… (але це специфічно для Zsh).
синенький

@blueyed, я оновив відповідь визначенням функції bash.
Акумен

Зауважте також -dопцію, щоб вказати роздільник; наприкладps -fp$(pgrep -d , getty)
Toby Speight

1
Я використовую це: ps uxp `pgrep <process>` Зауважте, що pцей параметр повинен бути останнім (тобто puxне працюватиме)
KFL

9

Ви можете фільтрувати в команді ps, наприклад

ps u -C gnome-terminal

(або пошук через / proc з пошуку тощо)


1
Зауважте, що це працює з PS GNU (Linux), але не з PS BSD.
Джош

Це неправильно, навіть якщо GNU ps. ps -C <command>відповідатиме точній команді. При використанні з параметрами aабо xвін повідомляє про всі процеси, тому що aі xперераховує процеси на додаток до набору процесів, які відповідають іншим способам.
Анімізм

@Animism True. Спасибі, я виправив це.
Андреас Фріш

Це працює лише в тому випадку, якщо назва процесу точно вказана. Це не працює для пошуку всіх слів, наприклад , logindдля systemd-logind, або відповідно аргументи.
Акумен

4

Ще одна альтернатива :

ps -fC terminal

Ось варіанти:

 -f        does full-format listing. This option can be combined
           with many other UNIX-style options to add additional
           columns. It also causes the command arguments to be
           printed. When used with -L, the NLWP (number of
           threads) and LWP (thread ID) columns will be added. See
           the c option, the format keyword args, and the format
           keyword comm.

 -C cmdlist     Select by command name.
                This selects the processes whose executable name is
                given in cmdlist.

6
Невеликий недолік і той, який насправді не пов'язаний з питанням ОП, полягає в тому, що це не покаже вам такі речі, як Tomcat, який насправді працює як java зі списком аргументів.
Чарльз Вуд

-Cваріант вже запропоновано у відповіді @Andreas Frishe, опублікованій на рік-півтора раніше…
Пьотр Доброгост

3

Використання дужок для оточення символу в шаблоні пошуку виключає grepпроцес, оскільки він не містить відповідного регулярного вираження.

$ ps ax | grep 'syslogd'
   16   ??  Ss     0:09.43 /usr/sbin/syslogd
18108 s001  S+     0:00.00 grep syslogd

$ ps ax | grep '[s]yslogd'
   16   ??  Ss     0:09.43 /usr/sbin/syslogd

$ ps ax | grep '[s]yslogd|grep'
   16   ??  Ss     0:09.43 /usr/sbin/syslogd
18144 s001  S+     0:00.00 grep [s]yslogd|grep

3

Відмова: Я автор цього інструменту, але ...

Я б використовував px :

~ $ px atom
  PID COMMAND          USERNAME   CPU RAM COMMANDLINE
14321 crashpad_handler walles   0.01s  0% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Electron Framework.framework/Resources/crashpad_handler --database=
16575 crashpad_handler walles   0.01s  0% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Electron Framework.framework/Resources/crashpad_handler --database=
16573 Atom Helper      walles    0.5s  0% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Atom Helper.app/Contents/MacOS/Atom Helper --type=gpu-process --cha
16569 Atom             walles   2.84s  1% /Users/walles/Downloads/Atom.app/Contents/MacOS/Atom --executed-from=/Users/walles/src/goworkspace/src/github.com/github
16591 Atom Helper      walles   7.96s  2% /Users/walles/Downloads/Atom.app/Contents/Frameworks/Atom Helper.app/Contents/MacOS/Atom Helper --type=renderer --no-san

За винятком пошуку процесів з розумним інтерфейсом командного рядка, він також робить багато інших корисних речей, більше деталей на сторінці проекту .

Працює на Linux та OS X, легко встановлюється:

curl -Ls https://github.com/walles/px/raw/python/install.sh | bash

0

Залежно від кінцевого випадку використання, вам часто хочеться віддати перевагу Awk.

ps aux | awk '/[t]erminal/'

Це особливо вірно, коли у вас є щось подібне

ps aux | grep '[t]erminal' | awk '{print $1}'  # useless use of grep!

де очевидно, що регулярний вираз може бути включений в сценарій Awk тривіально:

ps aux | awk '/[t]erminal/ { print $1 }'

Але дійсно, не винаходити це самостійно. pgrepі друзі існують давно, і вирішують весь цей проблемний простір набагато краще, ніж більшість спеціальних реалізацій.


-2

Інший варіант - відредагувати ваш .bash_profile(або інший файл, у якому ви зберігаєте псевдоніми bash), щоб створити функцію, яка виводить "grep" з результатів.

function mygrep {
grep -v grep | grep --color=auto $1
}

alias grep='mygrep'

grep -v grepПовинен бути першим в іншому випадку ваш--color=auto воля не працює з якої - то причини.

Це працює, якщо ви використовуєте bash; якщо ви використовуєте іншу оболонку YMMV.


1
Що з псевдонімом і функцією? Просто зробіть function grep { command grep -v grep | command grep --color=auto "$@"; }(також зверніть увагу на виправлення аргументу та цитування). Однак це порушено в тому, що будь-яке psневикликання grepволі більше не спрацює (аргументи передаються неправильно). У будь-якому разі набагато кориснішою функцією буде та, яка модифікує регулярний вираз, щоб він не відповідав собі, а не фільтрував grepз grepрезультатів окремо. І звичайно, винаходити нові рішення проблеми, яка була адекватно вирішена десятиліттями тому, не є дуже результативною.
трійчатка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.