Як я можу запобігти появі "grep" у результатах ps?


304

Коли я шукаю якийсь процес, який не існує, наприклад

$ ps aux | grep fnord                          
wayne    15745  0.0  0.0  13580   928 pts/6    S+   03:58   0:00 grep fnord

Очевидно, що мене не хвилює греп - це має стільки ж сенсу, як і пошук psпроцесу!

Як я можу запобігти появі грепу в результатах?


28
Якщо вам потрібен лише PID процесу, його можна замінити ps aux |grepна pgrep(або pgrep -f).
jofel

6
Те ж питання про Serverfault і суперкористувача .
Тор

це законний вихід? здається, що там немає програми з назвою fnord running ...
acolyte

4
@acolyte, саме це - але, оскільки він перетворює вихід у grep, grep працює (чекаю на вихід ps aux, я очікую). Таким чином, питання полягає в тому , щоб запобігти grep fnordпоказ в якості запущеного процесу , тому що , очевидно , я не зацікавлений в цьому один.
Уейн Вернер

2
@acolyte це не дивно, що ви не можете побачити рядок "fnord". Ви не повинні це бачити. Якщо у вас є запасні 2 або 3 хвилини, знайдіть її.
Франческо

Відповіді:


439

Виявляється, в брелоку знайдено рішення .

$ ps aux | grep "[f]nord"

Розміщуючи дужки навколо букви та лапок навколо рядка, ви шукаєте регулярний вираз, який говорить: "Знайдіть символ" f ", а потім" nord ".

Але оскільки ви поставили дужки у шаблоні 'f', тепер слідує ']', тому grepне відображатиметься у списку результатів. Неато!


26
@acolyte: Вихід з ps включатиме рядок, що закінчується на grep [f]nord. Однак цей рядок не буде входити через фільтр grep, оскільки рядок [f]nordне відповідає регулярному виразу [f]nord.
LarsH

9
@LarsH цікаво, дякую! я б запропонував ps aux | grep fnord | grep -v grep... що, здається, вже було запропоновано кількома людьми ... lol
аколіт

5
@progo Так, вам потрібно процитувати [навіть у bash. Спробуйте це з файлом, який називається fnordу поточному каталозі.
Жиль

25
Захоплення результатів psможе бути старою хитрістю, але це ненадійно. Використовуйтеpgrep за наявності.
Жиль

8
@naxa Уявіть, що у вас є програмний дзвінок fnordта програма, що називається safnorde. Або хтось викликає користувача bfnord, і ви в кінцевому підсумку вбиваєте всі його процеси. І т. Д.
Жиль

163

Інший варіант, який я використовую (особливо просто для того, щоб подивитися, чи працює процес), - це pgrep команда. Це дозволить здійснити пошук відповідного процесу, але не відобразить точну лінію для пошуку. Мені це подобається, тому що це швидкий спосіб пошуку, без повторного введення або уникнення нічого.

pgrep fnord

8
Вони захочуть, щоб -fваріант був більше схожим ps | grep.
Йорданм

@jordanm Власне, pgrep -fбуде виглядати більше ps -f | grep.
Michelpm

5
Існує також -lаргумент, щоб він показав команду, яка відповідає.
Патрік

15
ps | grep '[f]nord'розумний і поважний, але pgrep правильний .
kojiro

3
Ви завжди можете зробити це, ps $(pgrep cmd) ...якщо у `pgrep відсутні параметри (однак він не працює для порожнього набору команд).
Мацей П'єхотка

62

Ідеальне рішення - це рішення, представлене BriGuy

pgrep fnord 

Але якщо ви цього не хочете, ви можете просто виключити всі рядки, які збігаються з grep із:

ps aux | grep -v grep | grep "fnord"

7
але що, якщо лінія, яку я шукаю, - це "bash bash grep bash"?
Спарр

1
@Sparr Тоді вам слід скористатися найкращим рішенням: pgrepабо знайти інше;)
RSFalcon7

Слідкуйте за обмеженням довжини імені за допомогою pgrep. Використовуйте -f, щоб отримати повну назву шляху, або ви можете виявити, що ваші збіги не вдається з довшими іменами. -Я також приємно, щоб перерахувати матчі
Ніл Макгілл

25

Не найелегантніше рішення, але ви можете це зробити:

$ ps aux | grep fnord | grep -v grep


Це погана відповідь! Бо якби grepу вашій фразі було слово . Цей процес не покаже. Наприклад, припустимо, що файл, який називається foo_grep_bar.txt, редагується nanoкомандою. Отже, запускається процес: root 14908 0.0 0.0 110012 1692 pts / 3 S + Oct31 0:00 nano foo_grep_bar.txtВідповідно до цієї відповіді, це не буде працювати: $ ps aux | grep nano | grep -v grepТому що у вашому імені файлу є греппіве слово.
Набі КАЗ

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

1
згідно superuser.com/a/409658/450260 ви повинні бути за винятком повної grep fnordне тільки grepте $ ps aux | grep fnord | grep -v "grep fnord"
Давос

15

У Zsh, grep fnord =(ps aux).

Ідея полягає у тому, щоб спочатку запустити ps auxрезультат у файл, а потім використовувати grepу цьому файлі. Тільки у нас немає файлу, оскільки ми використовуємо "заміну процесу" zsh.

Для ілюстрації спробуйте

ps aux > ps.txt
grep fnord ps.txt
rm ps.txt

Результат повинен бути однаковим.

Загальний коментар до деяких інших відповідей. Деякі з них є складними та / або тривалими. Справа не лише в правильності, вона повинна бути корисною. Але це не означає, що деякі з цих рішень є поганими; лише вони повинні бути загорнуті в міні-інтерфейс користувача, щоб зробити їх корисними.


1
Не знаючи підстановки процесу zsh, але чи впевнено, що два процеси називаються один за одним, а не паралельно?
Paŭlo Ebermann

3
@ PaŭloEbermann: Для паралельних є <(command). grep grep =(ps aux)не показує жодного рядка
Мацей П'єхотка

Zsh також може «збільшити» вихід з ps. print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
Friartek

7
ps aux | grep $(echo fnord | sed "s/^\(.\)/[\1]/g")

3
це схоже на IOCCC, але для командного рядка unix замість C ^^ Просто | grep $(echo fnord)було недостатньо? Ви також запитуєте sed шукати та замінювати кожне char у "fnord" за власним значенням? ^^ привітань. Б'юсь об заклад, що я можу зробити ще довше, але це, мабуть, не буде так смішно ^^
Олів'є Дулак

1
Прошу вибачення за те, що тон мого вище коментаря може здатися образливим (і я не можу його відредагувати через 5 мільйонів) ... Ваша відповідь була справді радісною, і я не намагався змусити вас виглядати погано. Я дійсно думаю, що ви зробили це так цілеспрямовано ^^
Олів'є Дулак

1
Не вибачте, вашу відповідь було дуже цікаво читати (і спот-на-праву теж). Я мав на увазі pgrep -l $ 1 все одно;)
yPhil

3
@OlivierDulac: Він не просто замінює перший знак власною цінністю; він замінює це конкатенацією його значення серед квадратних дужок. (Ці квадратні дужки не є особливими, вони буквальні.) В основному, він узагальнює відповідь Уейна Вернера, щоб процес розміщення квадратних дужок навколо першого символу міг бути сценарієм. +1
LarsH

2
ps aux | grep '[^]]fnord'уникав би цього гімнастичного.
Стефан Шазелас

6

Ця відповідь стосується GNU . Дивіться відповідь Уейна для більш загального рішення.

Пошук процесів

Якщо ви просто шукаєте fnordпроцеси, ви можете скористатися -Cопцією для вибору за назвою команди:

ps -C fnord

Це можна змішати з параметрами формату BSD та POSIX на ваш смак. Дивіться сторінку людини пса для повного списку.

Шукаєте щось ще?

Якщо вам потрібно щось досконаліше, ніж точний пошук назви команди, не втрачайте надії! Це все ще можна зробити psзбоку від труби. Все, що нам потрібно зробити, - це сказати, psщоб виключити grepпроцеси з результату:

ps -NC grep | grep 'fnord'

-C grepвибирає всі греп-процеси та -Nвідміняє вибір. Це можна використовувати для пошуку аргументів команди, частини імені команди або більш складних регулярних виразів.


1
Це добре з GNU, psале -Cне визначено POSIX і має зовсім інше значення для BSD
Eric Renouf

Це дійсно облом, що немає еквівалента BSD (що також означає, що він не працює на mac). Використання ps -C - це найпростіший відповідь на будь-який із них.
Крістофер Хантер

3

Моя відповідь є варіацією типової відповіді для пошуку "foobar" у списку "ps". Я вважаю, що аргумент "-A" "ps" більш портативний, ніж "aux", але ця зміна не має значення. Типова відповідь виглядає приблизно так:

$ ps -A -ww | grep [f]oobar

Натомість я використовую цю схему:

$ ps -A -ww | grep [^]]foobar

Основна перевага полягає в тому, що простіше писати сценарії на основі цих шаблонів, оскільки ви просто з'єднаєте статичний рядок "[^]]" з будь-яким шаблоном, який ви шукаєте. Вам не потрібно знімати першу букву рядка, а потім вставити її між квадратними дужками, а потім знову з’єднати цю спільноту. Під час написання сценарію в оболонці простіше просто вставити "[^]]" перед шаблоном, який ви шукали для пошуку. Нарізка струн у Bash - це некрасива річ, тому мій варіант цього уникає. Цей варіант говорить про те, що показують рядки, де візерунок відповідає БЕЗ провідного правого квадратного дужки]. Оскільки схема пошуку для виключення квадратної дужки насправді додає квадратну дужку до шаблону, то вона ніколи не буде відповідати собі.

Отже, ви можете написати портативну команду psgrep таким чином. Тут я припускаю деякі відмінності між Linux, OS X BSD та іншими. Це додає заголовків стовпців з 'ps', надає більш спеціальний формат 'ps', який відповідає моїм потребам кращих категорій, і відображає процеси, що перераховують додатковий, надзвичайно широкий, так що жоден аргумент командного рядка не пропускається. Ну, більшість не пропускають. Ява, як Java, часто робить речі найгіршим можливим способом, тому деякі служби Java будуть проходити повз максимально дозволену довжину аргументів, яку буде відслідковувати таблиця процесів. Я вважаю, що це 1024 символи. Довжина команди, дозволена для запуску процесу, набагато довша, але таблиця процесу ядра не намагається відслідковувати що-небудь понад 1 К довжини. Після запуску команди команда-ім'я та список аргументів isn '

psgrep ()
{
    pattern=[^]]${1};
    case "$(uname -s)" in
        Darwin)
            ps -A -ww -o pid,ppid,nice,pri,pcpu,pmem,etime,user,wchan,stat,command | grep -i -e "^[[:space:]]*PID" -e ${pattern}
        ;;
        Linux)
            ps -A -ww -o pid,ppid,tid,nice,pri,pcpu,pmem,etime,user,wchan:20,stat,command | grep -i -e "^[[:space:]]*PID" -e ${pattern}
        ;;
        *)  # other UNIX flavors get a minimalist version.
            ps -A -ww | grep -i -e ${pattern}
        ;;
    esac
}

2

Найпростіший оболонку-агностик - це зберігати його в першій змінній:

PS_OUTPUT="$(ps aux)"; echo "$PS_OUTPUT" |grep fnord

Виклик: @ EmanuelBerg grep fnord =(ps aux)відповідь на сьогоднішній день є найелегантнішою, хоча і вимагає zsh. Я коротко мав це у своїх rc-файлах, але Баш скаржиться на цей синтаксис, навіть незважаючи на умовні умови, які повинні перешкоджати його оцінці.


З моїх файлів rc я маю нечутливу до регістру версію, яка бере аргументи grep:

psl() {
  local PS_OUTPUT="$(ps auxww)"
  echo "${PS_OUTPUT%%$'\n'*}" >&2  # title, in stderr to avoid pipes
  echo "${PS_OUTPUT#*$'\n'}" |grep -i "${@:-^}"
}

Пробіг коду, одна куля на рядок коду:

  • Захоплення багатослівного psвиводу (у localзмінній, щоб він зникав, коли функція повертається)
  • Показуйте перший рядок (заголовок) у стандартній помилці, щоб результати можна було додатково відфільтрувати, не впливаючи на заголовок. Підстановка говорить: взяти $PS_OUTPUTта видалити все після подачі першого рядка (regex equiv:) s/\n.*$//msg. Це заважає нам присвоїти назву
  • Відобразить psвихід із усім, окрім першого рядка (regex equiv:), s/^.*\n//mі змістіть його вміст з -iдля нечутливого до регістру та з усіма аргументами, переданими цією функцією (у разі відсутності аргументів ^, що відповідає початку будь-якого рядка, щоб відповідати все)

1

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

ps aux >f && grep tmpfs <f

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

Пропозиція щодо синтаксису послідовного оператора:

ps aux ||| grep tmpfs

Нездатність простих людей легко фільтрувати потік навряд чи є причиною для еліти базуватися на послідовностях. Це був би крок назад у обчисленні.
Acumenus

@ABB en.wikipedia.org/wiki/Communicating_sequences_process має набагато більше операторів, ніж ті, що опинилися в оболонці Томпсона. Просто міг бути оператор, який є послідовним, і який повідомляє про свій результат наступному процесу в послідовності, як тільки він закінчується. "Крок назад у обчисленні" шляхом надання додаткового оператора здається трохи суворим.
Енн ван Россум

Приємне посилання, але, звичайно, послідовна обробка гірша як у процесорі, так і у використанні пам'яті (або диска) - щодо паралельної обробки. У цьому випадку, якщо я повинен спочатку зберігати весь psвихід до мене grep, я використовую більше пам'яті (або диска) довше.
Acumenus

0

Команда pgrep, як заявили інші, поверне PID (ідентифікатор процесу) процесів на основі імені та інших атрибутів. Наприклад,

pgrep -d, -u <username> <string>

дасть вам PID, розмежовані комою (,) всіх процесів, ім’я яких відповідає користувачеві <username>. Ви можете використовувати перемикач -x раніше, щоб повернути лише точні збіги.

Якщо ви хочете отримати більше інформації про ці процеси (як це означає, що параметри aux з ps мають на увазі), ви можете використовувати опцію -p з ps, яка відповідає на основі PID. Так, наприклад,

ps up $(pgrep -d, -u <username> <string>)

дасть детальну інформацію про всі PID, які відповідають команді pgrep.


psне вдається, якщо pgrepповертає порожній набір. У мене є відповідь, яка спирається на ваше, і намагається вирішити це питання.
Acumenus

0

Ось простий приклад пошуку PID ssh-agentдля імені користувача, не показуючи PID самого grepпроцесу:

ps xu | grep "${USER}.*[ ]/usr/bin/ssh-agent" | awk '{print $1 $2;}'

Якщо ви хочете, наприклад, вбити ssh-agentпоточного користувача, ви можете скористатися наступною командою:

kill `ps xu | grep "${USER}.*[ ]/usr/bin/ssh-agent" | awk '{print $2;}'`

Щоб створити зручний псевдонім, додайте у файл ~ / .bashrc або ~ / .zshrc наступний код:

function function1 () {
    ps xu | grep "$1.*$2" | awk '{print $1" "$2" "$11;}'
}
alias mygrep="function1"

І використовувати псевдонім ось приклади, щоб змусити всіх вивчати регулярні вирази:

. /etc/profile #to make alias usable
mygrep ${USER} ${PROCESS_PATH}
mygrep ${USER} "[f]nord"
mygrep "[f]nord"
mygrep ".*[s]shd"

PS Я перевіряв ці команди лише на Ubuntu та Gentoo.


(1) Питання не говорить про те, що користувач шукає один із власних процесів - користувач може не знати власника процесу, якого він шукає. (2) Настільки вигадна, як ця відповідь, вона все-таки зазнала б невдачі, якби ви сказали "${USER}.* /usr/bin/ssh-agent". Це працює, тому що ви сказали [ ]; тобто ви просто використовуєте механізм прийнятої відповіді. Ви можете також просто grep "[s]sh-agent".
G-Man

Ти правий. (1) Я поділився тим, що може бути корисним, коли я час від часу опинявся перед цією сторінкою (2) Так, я використовував регулярне вираження, як у прийнятій відповіді. (3) Я оновив свою відповідь, щоб вона була такою самою, як прийнята, тому що краще, але я також показала, як зробити і псевдонім використовувати з наданим ім'ям користувача або без нього. (4) Також показано, як визначити функцію, хоча це не обов'язково, але працює цікаво, оскільки $ 1 і $ 2 не перетинаються. Thx # G-Man
Костянтин Загорський

-1

Ви можете це зробити легко, просто визначивши АЛІАС у своєму .bashrc подібному:

alias grep='grep -v grep | grep'

Не впевнений, хто з них проголосував чи чому, але це дозволяє вам використовувати повне використання ps, що pgrep не має.
оптициклічний

Мало того, що це ненароком виключає інші греп-процеси; це також порушує grepвикористання в інших випадках. Спробуйте echo I love grep | grep love.
trosos

@trosos Майже 11 років я був * nix-ing .. і ніколи не використовував цю схему ніколи ... можливо, наступного року, хоча - хто знає правильно.
a20

-1

Використання опції -x (точна відповідність) працювало для мене. Я поєднав його з -f (повний командний рядок), тому я міг точно співставити свій процес із:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"

Чи пояснить себе той, хто робить заклик по зворотному поводу? Протягом багатьох років я працюю над тим, щоб вирішити це питання для мене.
moodboom
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.