Как я могу предотвратить отображение 'grep' в результатах ps?

304

Когда я ищу какой-то процесс, который не существует, например,

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

Очевидно, меня не волнует grep - в этом столько же смысла, сколько и в поиске psпроцесса!

Как я могу предотвратить появление grep в результатах?

Уэйн Вернер
источник
28
Если вам нужен только PID процесса, вы можете заменить его ps aux |grepна pgrep(или pgrep -f).
Джофель
6
Тот же вопрос о Serverfault и суперпользователя .
Тор
этот вывод законен? кажется, что нет программы с именем fnord, работающей ...
помощник
4
@acolyte, это именно так - но поскольку он выводит вывод в grep, grep работает (ожидая вывода ps aux, я ожидаю). Таким образом, вопрос заключается в том, как предотвратить появление grep fnordв качестве запущенного процесса, потому что, очевидно, я не заинтересован в этом .
Уэйн Вернер
2
@acolyte неудивительно, что вы не видите строку "fnord". Вы не должны быть в состоянии увидеть это. Если у вас есть 2 или 3 минуты, поищите их.
Франческо

Ответы:

438

Оказывается, есть решение, найденное в связке ключей .

$ ps aux | grep "[f]nord"

Поставив квадратные скобки вокруг буквы и кавычки вокруг строки, вы ищете регулярное выражение, которое говорит: «Найдите символ« f », за которым следует« nord »».

Но поскольку вы поставили квадратные скобки в шаблоне, за «f» теперь следует «]», поэтому grepв списке результатов не будет отображаться. Neato!

Уэйн Вернер
источник
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в текущем каталоге.
Жиль
26
Подведение итогов psможет быть старой уловкой, но это ненадежно. Используйте,pgrep если доступно.
Жиль
9
@naxa Представьте, что у вас есть вызов fnordпрограммы и называется программа safnorde. Или есть пользователь по имени bfnord, и вы в конечном итоге убиваете все его процессы. И т.д.
Жиль
165

Другой вариант, который я использую (особенно для проверки, запущен ли процесс), - это pgrep команда. Это будет искать соответствующий процесс, но не будет отображать строку поиска для поиска. Мне это нравится, потому что это быстрый способ поиска, без регулярных выражений или экранирования.

pgrep fnord
BriGuy
источник
8
Они будут хотеть, чтобы -fопция была больше похожа ps | grep.
Иордания
@jordanm На самом деле, pgrep -fбудет выглядеть больше как ps -f | grep.
michelpm
5
Существует также -lаргумент, чтобы показать команду, которая соответствует.
Патрик
15
ps | grep '[f]nord'умный и почтенный, но pgrep прав .
Кодзиро
3
Вы всегда можете сделать это, ps $(pgrep cmd) ...если в `pgrep отсутствуют параметры (хотя он не будет работать для пустого набора команд).
Мачей Печотка
63

Идеальным решением является решение, представленное BriGuy

pgrep fnord 

Но если вы не хотите этого делать, вы можете просто исключить все строки, совпадающие с grep :

ps aux | grep -v grep | grep "fnord"
RSFalcon7
источник
7
но что, если строка, которую я ищу, это "bash bash grep bash"?
Спарр
1
@Sparr Тогда вы должны использовать лучшее решение: pgrepили найти другое;)
RSFalcon7
Следите за ограничением длины имени с помощью pgrep. Используйте -f, чтобы получить полный путь, иначе вы можете обнаружить, что совпадения не совпадают с более длинными именами. -Лю тоже приятно перечислять матчи
Нил МакГилл
24

Не самое элегантное решение, но вы можете сделать это:

$ 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потому что в вашем имени файла есть слово grep.
Наби КАЗ
Я предпочитаю это, поскольку оно более явно о его намерении, чем принятый ответ и работает во всех случаях, кроме одного.
samaspin
1
согласно superuser.com/a/409658/450260 вы должны исключать полное, а grep fnordне только grepто есть $ ps aux | grep fnord | grep -v "grep fnord"
Давос
14

В зш grep fnord =(ps aux).

Идея состоит в том, чтобы сначала запустить ps auxрезультат в файл, а затем использовать его grep. Только у нас нет файла, так как мы используем zsh «процесс подстановки».

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

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

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

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

Эмануэль Берг
источник
1
Не зная подстановку процессов в zsh, но уверен ли, что два процесса вызываются один за другим, а не параллельно?
Пауло Эберманн
3
@ PaŭloEbermann: для параллели это <(command). grep grep =(ps aux)не показывает ни одной строки.
Мачей Печотка
Zsh также может «соответствовать» выводу ps. print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
Friartek
6
ps aux | grep $(echo fnord | sed "s/^\(.\)/[\1]/g")
yPhil
источник
3
это похоже на IOCCC, но для командной строки Unix вместо C ^^ Просто | grep $(echo fnord)было недостаточно? Вы также просите Sed искать и заменять каждый символ в "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. Смотрите man-страницу ps для полного списка.

Ищете что-то еще?

Если вам нужно что-то более сложное, чем точный поиск имени команды, не теряйте надежды! Это все еще можно сделать на psстороне трубы. Все, что нам нужно сделать, это сказать, psчтобы исключить grepпроцессы из результата:

ps -NC grep | grep 'fnord'

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

Морган
источник
1
Это хорошо с GNU, psно -Cне определено POSIX и имеет совершенно другое значение для BSD
Эрик Ренуф
Это действительно облом, там нет эквивалента 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, она часто работает в наихудшем из возможных способов, поэтому некоторые 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

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


Из моих файлов 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и удалите все после первого перевода строки (регулярное выражение:) s/\n.*$//msg. Это мешает нам получить название
  • Выведите psвыходные данные со всем, кроме первой строки (regex эквивалента:) s/^.*\n//mи grep с его содержимым -iдля учета без учета регистра и со всеми аргументами, переданными этой функции (в случае отсутствия аргументов ^, что соответствует началу любой строки, чтобы соответствовать все)
Адам Кац
источник
1

Вот расширенная версия grep -v grepрешения, отфильтровывающая все grepпроцессы, которые не выполнялись более секунды, что является улучшением по сравнению с «просто отбрасывать все вхождения grep».

$ ps -ef | grep -vw "00:00:00 grep" | grep <searchTerm>

соответственно

$ ps aux | grep -vw "0:00 grep" | grep <searchTerm>

Это может быть не переносимым и зависит от фактического формата вывода вашей локальной psкоманды.

Вы можете объединить это с цветным grepвыводом для удобства:

$ alias grep='grep --color=auto'
Мерфи
источник
0

Может быть, пришло время использовать реальную последовательность на этот раз. Использование труб делает его параллельным.

ps aux >f && grep tmpfs <f

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

Предложение по синтаксису последовательного оператора:

ps aux ||| grep tmpfs
Энн ван Россум
источник
Неспособность простых людей легко фильтровать поток - едва ли причина для элиты основывать себя на последовательностях. Это был бы шаг назад в вычислительной технике.
Acumenus
@ABB en.wikipedia.org/wiki/Communicating_sequential_processes имеют гораздо больше операторов, чем те, которые оказались в оболочке Томпсона. Может быть просто оператор, который является последовательным, и который передал свой результат следующему процессу в последовательности, как только он выйдет. «Шаг назад в вычислениях» путем предоставления дополнительного оператора кажется немного резким.
Энн ван Россум
Хорошая связь, но, конечно, последовательная обработка хуже при использовании как процессора, так и памяти (или диска) - по сравнению с параллельной обработкой. В этом случае, если я должен сначала сохранить все psвыходные данные grep, я использую больше памяти (или диска) дольше.
Acumenus
0

Команда pgrep, как уже говорили другие, вернет PID (ID процесса) процессов на основе имени и других атрибутов. Например,

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

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

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

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

выдаст подробную информацию обо всех идентификаторах PID, соответствующих команде pgrep.

eToThePiIPower
источник
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
Константин Загорский
-2

Использование опции -x (точное совпадение) сработало для меня. Я объединил его с -f (полная командная строка), чтобы я мог точно сопоставить свой процесс с:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"
moodboom
источник
Объяснит ли кто-нибудь, кто делает прогон за рулем? Это работало, чтобы решить эту проблему для меня в течение многих лет.
moodboom
-3

Вы можете сделать это легко, просто с помощью определения ALIAS в вашем .bashrc виде:

alias grep='grep -v grep | grep'
Кейван Бейги
источник
Не уверен, кто проголосовал против или почему, но это позволяет вам использовать в полной мере ps, а pgrep - нет.
Оптически
1
Мало того, что это случайно исключает другие процессы grep; это также нарушает grepиспользование в других случаях. Попробуй echo I love grep | grep love.
Тросос
@trosos Почти 11 лет я * nix-ing ... и никогда не использовал этот шаблон когда-либо ... может быть, в следующем году - кто знает правильно.
а20