Bardziej elegancki „ps aux | grep -v grep ”

177

Kiedy sprawdzam listę procesów i „wyszukuję” te, które są dla mnie interesujące, to grepsamo w sobie jest uwzględniane w wynikach. Na przykład, aby wyświetlić listę terminali:

$ 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

Zwykle ps aux | grep something | grep -v greppozbywam się ostatniego wpisu ... ale nie jest elegancki :)

Czy masz bardziej elegancki sposób na rozwiązanie tego problemu (poza opakowaniem całego polecenia w osobny skrypt, co również nie jest złe)

Jakub M.
źródło
4
Warto, to jest starożytne FAQ. Zobacz punkt 3.10 na faqs.org/faqs/unix-faq/faq/part3
tripleee
1
Dzięki za odniesienie. To jest ich metoda:ps ux | awk '/name/ && !/awk/ {print $2}'
Jakub M.
Co grep -v greprobi ta część?
Jwan622,
2
@ Jwan622 grep -v grepwyklucza grepz wyników grep. Jeśli grep jest używany w połączeniu z ps, to proces grep (z argumentami grep) również zostanie wyświetlony, zaśmiecając wyniki. grep -v grep jest powszechnym sposobem uniknięcia tego
Eugene Platonov

Odpowiedzi:

282

Zwykła technika jest taka:

ps aux | egrep '[t]erminal'

Spowoduje to dopasowanie wierszy zawierających terminal, które egrep '[t]erminal'nie! Działa również na wielu odmianach Uniksa.

Johnsyweb
źródło
1
Działa to dla mnie dla dowolnego ciągu, ale nie dla nazwy użytkownika, np ps aux | grep '[r]oot'. Czy ktoś wie dlaczego?
kxsong
2
@kxsong: | grep '[t]erminal'wybiera dowolną linię zawierającą słowo „terminal” bez umieszczania słowa „terminal” na liście procesów. Co próbujesz osiągnąć | grep '[r]oot'i jak to nie działa? Prawdopodobnie będzie lepsze rozwiązanie.
Johnsyweb
3
Popraw mnie, jeśli się mylę, ale powinno to również działać na dowolnej pozycji grepowanego znaku: ps aux | grep "te [r] minal"
meso_2600
2
genialny Hack (myślę, że powinienem go tak nazwać, ponieważ aux / grep autorzy prawdopodobnie nie myśleć o tym scenariuszu.)
Michael Trouw
2
@JamieJag: Cóż ... tak jak powiedziałem w moim poście, grep '[t]erminal'dopasuje linie zawierające terminal. Wyjście z ps auxbędzie zawierało wiersz z grep '[t]erminal'(z nawiasami kwadratowymi), który nie zawiera łańcucha terminal(bez tego samego).
Johnsyweb
57

Użyj pgrep . Jest bardziej niezawodny.

DarkDust
źródło
pgrepnie zadziała, jeśli poszukam na przykładps aux | grep 'ssh options'
Jakub M.
12
Jakub M .: A co powiesz pgrep -f?
hillu
4
@ jakub-m Domyślnie pgrepdopasowuje wzorzec tylko do nazwy procesu. Aby dopasować się do całego polecenia, użyj -fflagi.
bluecollarcoder
3
pgrepzwraca tylko identyfikatory procesów.
Melab
1
starsze wersje zajęły pgrep -fl(ale nie można było zobaczyć pełnej linii cmd bez -fdopasowania pełnej linii cmd, szczegóły: serverfault.com/a/619788/44183 ). Ale tak, jeśli potrzebujesz innych informacji poza pid, cmdline, potrzebujesz ps. Można je połączyć:ps -p $(pgrep -f foo)
Beni Cherniavsky-Paskin
29

Ta odpowiedź opiera się na wcześniejszej pgrep odpowiedzi . Opiera się również na innej odpowiedzi, łączącej użycie psz pgrep. Oto kilka przykładów przydatnych szkoleń:

$ 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]

Powyższe może być używane jako funkcja :

$ 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

Porównaj z użyciem psz grep. Przydatny wiersz nagłówka nie jest drukowany:

$  ps aux | grep [s]shd
root      1902  0.0  0.1  82560  3580 ?        Ss   Oct20   0:00 /usr/sbin/sshd -D
Acumenus
źródło
Zobacz github.com/blueyed/oh-my-zsh/blob/… (ale jest to specyficzne dla Zsh).
niebieskawe
@blueyed, zaktualizowałem odpowiedź o definicję funkcji bash.
Acumenus
Zwróć też uwagę na -dmożliwość określenia separatora; np.ps -fp$(pgrep -d , getty)
Toby Speight
1
Używam tego: ps uxp `pgrep <process>` Zauważ, że pmusi to być ostatni parametr (tj. puxNie zadziała)
KFL
9

Możesz filtrować w poleceniu ps, np

ps u -C gnome-terminal

(lub przeszukaj / proc za pomocą find itp.)

Andreas Frische
źródło
1
Zauważ, że działa to z psami GNU (Linux), ale nie działa z psami z BSD.
Josh,
Jest to niepoprawne nawet w przypadku GNU ps. ps -C <command>dopasuje dokładnie polecenie. W przypadku użycia z opcjami alub xzgłosi wszystkie procesy, ponieważ ai wyświetli xlistę procesów oprócz zestawu procesów dopasowanych w inny sposób.
Animizm
@Animism True. Dzięki, naprawiłem to.
Andreas Frische
Działa to tylko wtedy, gdy nazwa procesu jest dokładnie określona. Nie działa dla częściowego dopasowania, np. logindDla systemd-logindlub do dopasowania argumentów.
Acumenus
4

Jeszcze jedna alternatywa :

ps -fC terminal

Tutaj opcje:

 -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.
TaXXoR
źródło
6
Drobną wadą, która nie jest tak naprawdę związana z pytaniem OP, jest to, że nie pokaże ci rzeczy takich jak Tomcat, który jest faktycznie uruchamiany jako java z listą argumentów do prania.
Charles Wood
-Copcja została już zasugerowana w odpowiedzi @Andreasa Frishe'a zamieszczonej ponad półtora roku wcześniej…
Piotr Dobrogost
3

Użycie nawiasów do otaczania znaku we wzorcu wyszukiwania wyklucza grepproces, ponieważ nie zawiera pasującego wyrażenia regularnego.

$ 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
auntchilada
źródło
3

Zastrzeżenie: jestem autorem tego narzędzia, ale ...

Użyłbym 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

Oprócz znajdowania procesów z rozsądnym interfejsem wiersza poleceń, robi również wiele innych przydatnych rzeczy, więcej szczegółów na stronie projektu .

Działa na Linuksie i OS X, łatwa instalacja:

curl -Ls https://github.com/walles/px/raw/python/install.sh | bash
Johan Walles
źródło
0

W zależności od ostatecznego przypadku użycia często wolisz zamiast tego awk.

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

Jest to szczególnie prawdziwe, gdy masz coś takiego

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

gdzie oczywiście wyrażenie regularne można w trywialny sposób uwzględnić w skrypcie Awk:

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

Ale tak naprawdę, nie wymyślaj tego na nowo. pgrepi przyjaciele są w pobliżu od dawna i radzą sobie z całym problemem znacznie lepiej niż większość reimplementacji ad hoc.

tripleee
źródło
-2

Inną opcją jest edycja .bash_profilepliku (lub innego pliku, w którym przechowujesz aliasy bash), aby utworzyć funkcję, która usuwa słowo „grep” z wyników.

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

alias grep='mygrep'

grep -v grepMa być pierwszym w przeciwnym razie --color=autonie będzie działać z jakiegoś powodu.

Działa to, jeśli używasz basha; jeśli używasz innej powłoki YMMV.

FlyingCodeMonkey
źródło
1
O co chodzi z aliasem i funkcją? Po prostu zrób function grep { command grep -v grep | command grep --color=auto "$@"; }(zwróć także uwagę na poprawkę argumentu i cytowanie). Jednak jest to zepsute przez to, że żadne pswywołanie grepnie będzie już działać (argumenty są przekazywane niepoprawnie). W każdym razie, o wiele bardziej przydatna funkcja będzie jeden, który zmienia regex, aby to nie pasuje do siebie, zamiast odfiltrować grepz grepwyników oddzielnie. I oczywiście wymyślanie nowych rozwiązań problemu, który został odpowiednio rozwiązany dziesiątki lat temu, nie jest zbyt produktywne.
tripleee