Як не допустити "ps" повідомляти про власний процес?


52
$ ps | grep django
28006 ttys004    0:01.12 /usr/bin/python bin/django celeryd --beat
51393 ttys005    0:01.45 /usr/bin/python bin/django celeryd -l INFO
51472 ttys005    0:01.29 /usr/bin/python bin/django celeryd -l INFO
51510 ttys005    0:01.89 /usr/bin/python bin/django celeryd -l INFO
51801 ttys005    0:01.83 /usr/bin/python bin/django celeryd -l INFO
53470 ttys005    0:03.97 /usr/bin/python bin/django celeryd -l INFO
53780 ttys005    0:00.00 grep django

Чи є спосіб запобігти повідомленню про останній процес (тобто grep, який був запущений одночасно з моєю командою ps)?

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

Відповіді:


14

Моя відповідь є варіацією типової відповіді для пошуку "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 К довжини. Після запуску команди список імен команди та аргументів не потрібен, тому те, що зберігається в таблиці процесів, є лише інформаційним.

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
}

Недоліком є ​​те, що це насправді відповідає одному знаку більше (спереду), ніж оригінальний візерунок. Для прикладу, це ніколи не відповідає PID. І може бути трохи оманливим при використанні grep --colour.
Тонін

67

+1 для короткої відповіді @jamzed, однак ОП може потребувати деяких пояснень:

ps | grep "[d]jango"

Використовуючи цей регекс, ви запускаєте процес, який його рядок ps сам по собі не буде відповідати, оскільки регулярний вираз відповідає "django"і не відповідає "[d]jango". Таким чином ви виключите процес, який містить рядок "[d] jango", який у цьому випадку є grep; Те саме можна застосувати до pgrep, egrep, awk, sed тощо ... залежно від команди, яку ви використовували для визначення регулярного вираження.

Від людини 7 регекс

   A bracket expression is a list of characters enclosed in "[]".  It nor‐
   mally matches any single character from the list (but see  below).   If
   the  list  begins  with  '^',  it matches any single character (but see
   below) not from the rest of the list.  If two characters  in  the  list
   are  separated  by '-', this is shorthand for the full range of charac‐
   ters between those two (inclusive) in the collating sequence, for exam‐
   ple,  "[0-9]" in ASCII matches any decimal digit.  It is illegal(!) for
   two ranges to share an endpoint, for example, "a-c-e".  Ranges are very
   collating-sequence-dependent,  and portable programs should avoid rely‐
   ing on them.

2
Класно. Я насправді досить комфортний з регулярними виразами, але не міг одразу придумати спосіб, як запобігти збіженню регулярного виразу. Укладання букви у квадратних дужках має ідеальний сенс. (Включаючи щось на кшталт [^!] Також спрацювало б ...)
Стів Беннетт

1
Це приємно і хитро.
попіл

Для конкретного випадку 'ps' я використовую '[]' на передній частині імені процесу, який я шукаю. Тоді мені не потрібно розбирати ім'я процесу спеціально для регулярного виразу, але він все одно відповідає.
Нероманс

@hmontoliu Вона не працює, наприклад: ps aux | grep [s]cript1. Не могли б ви допомогти прокоментувати рішення?
ДУЮ

@hmontoliu Моя вина. Здається, рядок показаний через попередні пошуки ...
SOUser

30

ps | grep [d]jango

ps | grep d[j]ango

...

ps | grep djang[o]


Додати місце , якщо вам потрібно Grep один символ:ps aux| grep "[Z] "
AD

@jamzed Це не працює, наприклад: ps aux | grep [s]cript1або ps aux | grep [s]cript2. Лінія греппу все ще відображається. Не могли б ви допомогти прокоментувати рішення?
ДУЮ

@jamzed Моя вина. Здається, рядок показаний через попередні пошуки ...
SOUser

18

Замість цього використовуйте pgrep: pgrep -lf django


Як завжди, я забув згадати про платформу (OS X в цьому випадку). Імовірно, pgrep працює на різних Linux.
Стів Беннетт

Я не згоден, @ramruma. Я прийшов до цієї теми саме тому, що pgrepзадає мені саме цю проблему. Але мушу сказати, що я тестую його в CygWin (де psне можна показати повний командний рядок процесу).
Sopalajo de Arrierez

У посібнику зазначено: "Запущений процес pgrep або pkill ніколи не буде повідомляти про себе як про збіг", і я дійсно не бачив цього робити.
дельтаб

Я щойно стикався з проблемою, де я вважав, що pgrepвідповідає собі. Виявляється, воно відповідало імені bashфайлу сценарію, з якого я його запускав. Додавши -xфіксовану його, тоді вона відповідає точному імені команди.
andynormancx

11

О, зачекайте, це працює:

ps | grep django | grep -v grep

7
Тільки якщо командний рядок процесу не містить законних дій grep, на що ви не можете розраховувати в загальному випадку.
CVn

8

ps -d | grep django

від людини ps:

 -d                  Lists information  about  all  processes
                     except session leaders.

все ще показує греп на моєму ...
Кевін

Так, це працює для мене на OS X.
Стів Беннетт

Не працює на Linux.
Acumenus

Загалом, варіанти, psяк відомо, не є портативними, тому без інформації про те, для якої платформи це відповідь, ця відповідь не дуже корисна. Крім того, це, очевидно, недостатньо, коли ви не впевнені, що процес, який ви шукаєте, не є лідером процесу (тобто це може допомогти, якщо ваша мета - демон, але взагалі не інакше).
трійчатка

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