Jak mogę zapobiec wyświetlaniu „grep” w wynikach ps?


304

Gdy szukam jakiegoś procesu, który nie istnieje, np

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

Oczywiście nie obchodzi mnie grep - to ma tyle samo sensu, co poszukiwanie psprocesu!

Jak mogę zapobiec wyświetlaniu grep w wynikach?


28
Jeśli potrzebujesz tylko PID procesu, można zastąpić ps aux |grepz pgrep(lub pgrep -f).
jofel 30.04.13

6
To samo pytanie na ServerFault i główny użytkownik .
Thor

czy to wyjście jest legalne? wydaje się, że nie ma uruchomionego programu o nazwie fnord ...
acolyte

4
@ akolit, to jest dokładnie to - ale ponieważ przesyła dane wyjściowe do grep, grep działa (czekam na wyjście ps aux, oczekuję). Więc pytanie, jak zapobiec grep fnordwyświetlaniu się jako proces wyświetlane, ponieważ oczywiście nie jestem zainteresowany w tym jeden.
Wayne Werner

2
@acolyte nie jest zaskoczeniem, że nie widzisz linii „fnord”. Nie powinieneś tego widzieć. Jeśli masz jakieś 2 lub 3 minuty do stracenia, wyszukaj je.
Francesco

Odpowiedzi:


439

Okazuje się, że istnieje rozwiązanie znalezione w pęku kluczy .

$ ps aux | grep "[f]nord"

Umieszczając nawiasy wokół litery i cudzysłowu wokół łańcucha, szukasz wyrażenia regularnego, które brzmi: „Znajdź znak„ f ”, a następnie„ nord ”.

Ale ponieważ wstawiłeś nawiasy kwadratowe do wzoru „f”, po którym następuje teraz „]”, więc grepnie pojawi się na liście wyników. Neato!


26
@ acolyte: Dane wyjściowe z ps będą zawierać wiersz kończący się na grep [f]nord. Jednak ta linia nie przejdzie przez filtr grep, ponieważ ciąg [f]nordnie pasuje do wyrażenia regularnego [f]nord.
LarsH

9
@LarsH ciekawe, dzięki! zasugerowałbym ps aux | grep fnord | grep -v grep... co wydaje się już zasugerowane przez kilka osób ... lol
acolyte

5
@progo Tak, musisz zacytować [nawet w bash. Wypróbuj z plikiem nazwanym fnordw bieżącym katalogu.
Gilles

25
Poprawianie wyników psmoże być starą sztuczką, ale jest niewiarygodne. Użyj,pgrep jeśli jest dostępna.
Gilles

8
@naxa Wyobraź sobie, że masz wywołanie programu fnordi wywołany program safnorde. Albo zadzwonił użytkownik bfnord, a ty zabiłeś wszystkie jego procesy. Itd.
Gilles

163

Inną opcją, której używam (szczególnie po to, by sprawdzić, czy proces jest uruchomiony), jest pgrep polecenie. Spowoduje to wyszukanie pasującego procesu, ale nie wyświetli linii grep dla wyszukiwania. Podoba mi się, ponieważ jest to szybki sposób wyszukiwania, bez wyrażania regularnego lub ucieczki.

pgrep fnord

8
Będą chcieli, aby ta -fopcja była bardziej podobna ps | grep.
Jordan

@jordanm Właściwie pgrep -fbędzie wyglądać bardziej ps -f | grep.
michelpm

5
Istnieje również -largument, aby pokazać pasujące polecenie.
Patrick

15
ps | grep '[f]nord'jest sprytny i czcigodny, ale pgrep ma rację .
kojiro

3
Zawsze możesz to zrobić, ps $(pgrep cmd) ...jeśli w `pgrep brakuje opcji (nie działa to jednak dla pustego zestawu poleceń).
Maciej Piechotka

62

Idealnym rozwiązaniem jest to przedstawione przez BriGuy

pgrep fnord 

Ale jeśli nie chcesz tego robić, możesz po prostu wykluczyć wszystkie wiersze pasujące do grep z:

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

7
ale co jeśli linia, której szukam, to „bash bash grep bash”?
Sparr

1
@Sparr W takim razie powinieneś użyć najlepszego rozwiązania: pgreplub znaleźć inne;)
RSFalcon7

Uważaj na limit długości nazwy za pomocą pgrep. Użyj -f, aby uzyskać pełną nazwę ścieżki, a może się okazać, że dopasowania nie powiodą się przy dłuższych nazwach. -l też miło jest wymienić mecze
Neil McGill,

25

Nie jest to najbardziej eleganckie rozwiązanie, ale możesz to zrobić:

$ ps aux | grep fnord | grep -v grep


To zła odpowiedź! Bo jeśli grepw twoim wyrażeniu było słowo . Nie pokaże tego procesu. Załóżmy na przykład, że wywołany plik foo_grep_bar.txtjest edytowany przez nanopolecenie. Trwa proces: root 14908 0.0 0.0 110012 1692 pts / 3 S + Oct31 0:00 nano foo_grep_bar.txtzgodnie z tą odpowiedzią to nie zadziała: $ ps aux | grep nano | grep -v grepponieważ w nazwie pliku znajduje się słowo grep.
Nabi KAZ

Wolę to, ponieważ jest bardziej wyraźne na temat jego zamiaru niż zaakceptowana odpowiedź i działa we wszystkich przypadkach oprócz jednego.
samaspin

1
jak na superuser.com/a/409658/450260 powinieneś wykluczyć pełny grep fnordnie tylko greptj. $ ps aux | grep fnord | grep -v "grep fnord"
Davos

15

W zsh, grep fnord =(ps aux).

Chodzi o to, aby najpierw uruchomić ps aux, umieścić wynik w pliku, a następnie użyć go grepw tym pliku. Tylko, że nie mamy pliku, ponieważ używamy „podstawienia procesu” zsh.

Aby to zilustrować, spróbuj

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

Wynik powinien być taki sam.

Ogólny komentarz do niektórych innych odpowiedzi. Niektóre są zbyt skomplikowane i / lub wymagają długiego pisania. To nie tylko kwestia racji, ale także użyteczności. Ale to nie znaczy, że niektóre z tych rozwiązań są złe; tylko muszą być owinięte w mini-interfejs użytkownika, aby były użyteczne.


1
Nie znając podstawienia procesu zsh, ale czy jest pewne, że oba procesy są nazywane jeden po drugim, a nie równolegle?
Paŭlo Ebermann

3
@ PaŭloEbermann: Dla równoległości jest <(command). grep grep =(ps aux)nie pokazuje żadnej linii.
Maciej Piechotka

Zsh może również „dopasować” wyjście z ps. print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
Friartek

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

3
to wygląda jak IOCCC, ale dla linii poleceń unix zamiast C ^^ Po prostu | grep $(echo fnord)nie wystarczyło? prosisz także sed, aby przeszukał i zastąpił każdy znak w „fnord” swoją wartością? ^^ gratulacje. Założę się, że mogę zrobić jeszcze dłuższy, ale prawdopodobnie nie będzie tak zabawny ^^
Olivier Dulac

1
Przepraszam, ponieważ ton mojego powyższego komentarza może brzmieć obraźliwie (i nie mogę go edytować po 5 minutach) ... Twoja odpowiedź była naprawdę radosna, a ja nie próbowałem sprawić, byś wyglądał źle. Naprawdę myślę, że zrobiłeś to celowo ^^
Olivier Dulac

1
Nie przepraszaj, twoja odpowiedź była naprawdę fajna do przeczytania (i trafienia też w prawo). Miałem na myśli pgrep -l $ 1;)
yPhil 30.04.13

3
@OlivierDulac: On nie tylko zastępuje pierwszy znak własną wartością; zastępuje go konkatenacją jego wartości w nawiasach kwadratowych. (Te nawiasy kwadratowe nie są wyjątkowe, są dosłowne.) Zasadniczo uogólnia na odpowiedź Wayne'a Wernera, dzięki czemu proces umieszczania nawiasów kwadratowych wokół pierwszego znaku może być skryptowany. +1
LarsH

2
ps aux | grep '[^]]fnord'uniknąłby tego gimnastyki.
Stéphane Chazelas

6

Ta odpowiedź jest specyficzna dla GNU . Zobacz odpowiedź Wayne'a na bardziej ogólne rozwiązanie.

Wyszukiwanie procesów

Jeśli szukasz tylko fnordprocesów, możesz użyć -Copcji, aby wybrać według nazwy polecenia:

ps -C fnord

Można to mieszać z opcjami formatu BSD i POSIX według własnych upodobań. Zobacz stronę man ps, aby uzyskać pełną listę.

Szukasz czegoś innego?

Jeśli potrzebujesz czegoś bardziej zaawansowanego niż dokładne wyszukiwanie nazwy polecenia, nie trać nadziei! Nadal można to zrobić z psboku rury. Wszystko, co musimy zrobić, to powiedzieć, psaby wykluczyć grepprocesy z wyniku:

ps -NC grep | grep 'fnord'

-C grepzaznacza wszystkie procesy grep i -Nneguje wybór. Można tego użyć do wyszukiwania argumentów poleceń, części nazwy polecenia lub bardziej złożonych wyrażeń regularnych.


1
Jest to dobre z GNU, psale -Cnie jest określone przez POSIX i ma zupełnie inne znaczenie dla BSD
Eric Renouf

To naprawdę bummer, że nie ma odpowiednika BSD (co oznacza również, że nie będzie działać na Macu). Użycie ps-C jest zdecydowanie najprostszą odpowiedzią na którekolwiek z nich.
Christopher Hunter,

3

Moja odpowiedź jest odmianą typowej odpowiedzi dla wyszukiwania „foobar” na liście „ps”. Argument „-A” „ps” jest bardziej przenośny niż „aux”, jak sądzę, ale ta zmiana nie ma znaczenia dla odpowiedzi. Typowa odpowiedź wygląda następująco:

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

Zamiast tego używam tego wzoru:

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

Główną zaletą jest to, że łatwiej jest pisać skrypty oparte na tych wzorcach, ponieważ po prostu łączy się ciąg statyczny „[^]]” z dowolnym wzorcem, którego szukasz. Nie musisz zdejmować pierwszej litery sznurka, a następnie wstawiać go między kwadratowe nawiasy klamrowe, a następnie ponownie łączyć je z powrotem. Podczas pisania skryptów w powłoce łatwiej jest po prostu wcisnąć „[^]]” przed wzorkiem, którego szukałeś. Przecinanie strun w Bash jest brzydką rzeczą, więc moja odmiana tego unika. Ta odmiana mówi, że pokaż linie, w których wzór pasuje BEZ wiodącego prawego nawiasu kwadratowego]. Ponieważ wzorzec wyszukiwania wykluczający nawias kwadratowy faktycznie dodaje nawias kwadratowy do wzorca, nigdy nie będzie pasował do siebie.

Możesz napisać przenośne polecenie psgrep w następujący sposób. Tutaj uwzględniam różnice między Linuksem, OS X BSD i innymi. Dodaje to nagłówki kolumn z „ps”, zapewnia bardziej niestandardowy format „ps”, który lepiej odpowiada moim potrzebom, i wyświetla procesy z listą wyjątkowo, bardzo szeroką, aby żaden z argumentów wiersza poleceń nie został pominięty. Cóż, większość nie jest pominięta. Java, która jest Javą, często robi wszystko w najgorszy możliwy sposób, więc niektóre usługi java będą działać po przekroczeniu maksymalnej dozwolonej długości argumentów, które śledzi tabela procesów. Myślę, że to 1024 znaki. Długość pojedynczego polecenia pozwalająca na uruchomienie procesu jest znacznie dłuższa, ale tabela procesów jądra nie zadaje sobie trudu, aby śledzić wszystko o długości przekraczającej 1 K. Po uruchomieniu polecenia nazwa-polecenia i lista argumentów nie są

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

Najprostszym sposobem, aby to zrobić, jest przechowywanie go najpierw w zmiennej:

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

Call-out: Odpowiedź @ EmanuelBerg grep fnord =(ps aux)jest zdecydowanie najbardziej elegancka, choć wymaga zsh. Na krótko miałem go w moich plikach rc, ale bash narzeka na tę składnię, nawet pomimo warunku, który powinien uniemożliwić jego ocenę.


Z moich plików rc mam wersję bez rozróżniania wielkości liter, która pobiera argumenty grep:

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

Spacer po kodzie, jeden punkt w wierszu kodu:

  • Przechwyć pełne psdane wyjściowe (w localzmiennej, aby zniknęły po powrocie funkcji)
  • Wyświetl pierwszy wiersz (tytuł) ze standardowym błędem, aby wyniki mogły być dalej filtrowane bez wpływu na tytuł. Podstawienie mówi: weź $PS_OUTPUTi usuń wszystko po pierwszym wierszu (regex equiv:) s/\n.*$//msg. To uniemożliwia nam grepowanie tytułu
  • Wyświetl pswynik ze wszystkim oprócz pierwszego wiersza (regex equiv:) s/^.*\n//mi grep jego zawartość, -iaby nie rozróżniać wielkości liter i ze wszystkimi argumentami przekazanymi tej funkcji (w przypadku braku argumentów ^, co odpowiada początkowi dowolnego pasującego wiersza wszystko)

1

Może tym razem czas na użycie prawdziwej sekwencji. Zastosowanie rur sprawia, że ​​jest równoległy.

ps aux >f && grep tmpfs <f

Brzydkie, ponieważ będzie plik f, ale to nie moja wina, że ​​nie ma składni dla procesów sekwencyjnych, w których nadal chcesz korzystać z danych wyjściowych wcześniej uruchomionego procesu.

Sugestia dotycząca składni operatora sekwencyjnego:

ps aux ||| grep tmpfs

Brak możliwości zwykłego filtrowania strumienia przez zwykłych ludzi nie jest powodem, dla którego elita opiera się na sekwencjach. Byłby to krok wstecz w informatyce.
Acumenus,

@ABB en.wikipedia.org/wiki/Communicating_sequential_processes ma znacznie więcej operatorów niż tych, które znalazły się w powłoce Thompson. Mogłoby być po prostu operator, który jest sekwencyjny i który przekazał swój wynik do następnego procesu w sekwencji zaraz po jego wyjściu. „Krok wstecz w obliczeniach” poprzez zapewnienie dodatkowego operatora wydaje się nieco trudny.
Anne van Rossum,

Ładne łącze, ale oczywiście przetwarzanie sekwencyjne jest gorsze zarówno pod względem wykorzystania procesora, jak i pamięci (lub dysku) - w porównaniu z przetwarzaniem równoległym. W tym przypadku, jeśli najpierw muszę zapisać wszystkie psdane wyjściowe grep, używam więcej pamięci (lub dysku) na dłużej.
Acumenus,

0

Komenda pgrep, jak stwierdzili inni, zwróci PID (identyfikator procesu) procesów na podstawie nazwy i innych atrybutów. Na przykład,

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

poda Ci PID, oddzielone przecinkami (,) wszystkich procesów, których nazwy są uruchamiane przez użytkownika <username>. Możesz użyć przełącznika -x wcześniej, aby zwrócić tylko dokładne dopasowania.

Jeśli chcesz uzyskać więcej informacji o tych procesach (jak sugeruje uruchomienie opcji Aux z ps), możesz użyć opcji -p z ps, która jest zgodna z PID. Na przykład

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

poda szczegółowe informacje o wszystkich PID odpowiadających poleceniu pgrep.


pskończy się niepowodzeniem, jeśli pgrepzwraca pusty zestaw. Mam odpowiedź, która opiera się na twojej i próbuje rozwiązać ten problem.
Acumenus

0

Oto prosty przykład znalezienia PID ssh-agentdla nazwy użytkownika bez pokazywania PID grepsamego procesu:

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

Jeśli chcesz na przykład zabić ssh-agentdla bieżącego użytkownika, możesz użyć następującego polecenia:

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

Aby utworzyć przydatny alias, dodaj do pliku ~ / .bashrc lub ~ / .zshrc następujący kod:

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

I użycie tutaj aliasu to przykłady, które zmuszają wszystkich do nauki wyrażeń regularnych:

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

PS Testowałem te polecenia tylko na Ubuntu i Gentoo.


(1) Pytanie nie mówi, że użytkownik szuka jednego ze swoich procesów - użytkownik może nie znać właściciela poszukiwanego procesu. (2) Jakkolwiek wymyślna jest ta odpowiedź, nadal by się nie powiedzieli, gdybyś powiedział "${USER}.* /usr/bin/ssh-agent". Działa, ponieważ powiedziałeś [ ]; tzn. po prostu używasz mechanizmu przyjętej odpowiedzi. Równie dobrze możesz grep "[s]sh-agent".
G-Man,

Masz rację. (1) Udostępniłem to, co może być przydatne, ponieważ od czasu do czasu znalazłem się na tej stronie (2) Tak, użyłem wyrażenia regularnego jak w zaakceptowanej odpowiedzi. (3) Zaktualizowałem swoją odpowiedź, aby była taka sama, jak zaakceptowana, ponieważ ta jest lepsza, ale pokazałem również, jak tworzyć i używać aliasu z podaną nazwą użytkownika lub bez niego. (4) Pokazano także, jak zdefiniować funkcję, chociaż nie jest to konieczne, ale działa w interesujący sposób, ponieważ 1 $ i 2 $ nie pokrywają się. Thx # G-Man
Constantin Zagorsky

-1

Możesz to zrobić łatwo, po prostu definiując ALIAS w .bashrc taki sposób:

alias grep='grep -v grep | grep'

Nie jestem pewien, kto obniżył głos i dlaczego, ale pozwala to na pełne wykorzystanie ps, którego nie robi pgrep.
opticyclic

Nie tylko to przypadkowo wyklucza inne procesy grep; psuje również grepużycie w innych przypadkach. Spróbować echo I love grep | grep love.
trosos

@trosos Prawie 11 lat byłem * nix-ingiem ... i nigdy nie użyłem tego wzoru ... może jednak w przyszłym roku - kto wie dobrze.
a20

-1

Użycie opcji -x (dopasowanie ścisłe) działało dla mnie. Połączyłem go z -f (pełna linia poleceń), aby dokładnie dopasować mój proces do:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"

Czy ktokolwiek robi przewrotne głosowanie, wyjaśni się? Przez lata pracowałem nad rozwiązaniem tego problemu.
moodboom
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.