Mais elegante “ps aux | grep -v grep ”

177

Quando eu checo a lista de processos e 'saúdo' aqueles que são interessantes para mim, o greppróprio também é incluído nos resultados. Por exemplo, para listar terminais:

$ 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

Normalmente eu uso ps aux | grep something | grep -v greppara me livrar da última entrada ... mas não é elegante :)

Você tem um hack mais elegante para resolver esse problema (além de agrupar todo o comando em um script separado, o que também não é ruim)

Jakub M.
fonte
4
Para o que vale a pena, este é um FAQ antigo. Veja o item 3.10 em faqs.org/faqs/unix-faq/faq/part3
tripleee
1
Obrigado pela referência. Esse é o seu método:ps ux | awk '/name/ && !/awk/ {print $2}'
Jakub M.
O que a grep -v grepparte está fazendo?
precisa saber é o seguinte
2
@ Jwan622 grep -v grepexclui grepdos resultados grep. Se grep for usado em combinação com ps, o processo grep (com argumentos grep) também será mostrado, sobrecarregando seus resultados. grep -v grep é uma forma comum para evitar que
Eugene Platonov

Respostas:

282

A técnica usual é esta:

ps aux | egrep '[t]erminal'

Isso corresponderá às linhas que contêm terminal, o que egrep '[t]erminal'não! Também funciona em muitos sabores do Unix.

Johnsyweb
fonte
1
Isso funciona para mim para uma string arbitrária, mas não para um nome de usuário, por exemplo ps aux | grep '[r]oot'. Alguem sabe por quê?
kxsong
2
@kxsong: | grep '[t]erminal'seleciona qualquer linha que contenha a palavra 'terminal' sem colocar a palavra 'terminal' na lista de processos. O que você está tentando alcançar | grep '[r]oot'e como isso não está funcionando? É provável que haja uma solução melhor.
#
3
Corrija-me se estiver errado, mas isso também deve funcionar em qualquer posição do caractere grepped: ps aux | grep "te [r]
minal
2
brilhante corte (eu acho que deveria chamá-lo de que, desde o aux / autores grep provavelmente não pensar nesse cenário.)
Michael Trouw
2
@JamieJag: Bem ... como eu disse no meu post, grep '[t]erminal'corresponderá às linhas que contêm terminal. A saída de ps auxterá uma linha com grep '[t]erminal'(com colchetes), que não contém a sequência terminal(sem o mesmo).
Johnsyweb
57

Use pgrep . É mais confiável.

DarkDust
fonte
pgrepnão vai funcionar se eu olhar por exemplo, paraps aux | grep 'ssh options'
Jakub M.
12
Jakub M .: Que tal pgrep -f?
Hillu
4
@ jakub-m Por padrão, pgrepapenas corresponde ao padrão com o nome do processo. Para combinar com o comando inteiro, use a -fbandeira.
precisa
3
pgrepretorna apenas IDs de processo.
MELAB
1
versões anteriores foram obtidas pgrep -fl(mas não foi possível ver o cmdline completo sem -fcorresponder ao cmdline completo, detalhes: serverfault.com/a/619788/44183 ). Mas sim, se você precisar de outras informações além de pid, cmdline, precisará ps. Pode combiná-los:ps -p $(pgrep -f foo)
Beni Cherniavsky-Paskin
29

Esta resposta baseia-se em uma pgrep resposta anterior . Também se baseia em outra resposta combinando o uso de pswith pgrep. Aqui estão alguns exemplos de treinamento pertinentes:

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

O acima pode ser usado como uma função :

$ 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

Compare com o uso pscom grep. A linha do cabeçalho útil não é impressa:

$  ps aux | grep [s]shd
root      1902  0.0  0.1  82560  3580 ?        Ss   Oct20   0:00 /usr/sbin/sshd -D
Acumenus
fonte
Veja github.com/blueyed/oh-my-zsh/blob/… (mas é específico para o Zsh).
blueyed 23/03
@ blueyed, atualizei a resposta com a definição da função bash.
Acumenus 23/03
Observe também a -dopção para especificar um separador; por exemplops -fp$(pgrep -d , getty)
Toby Speight
1
Eu uso isso: ps uxp `pgrep <process>` Note que pdeve ser o último parâmetro (ou seja, puxnão vai funcionar)
KFL
9

Você pode filtrar no comando ps, por exemplo

ps u -C gnome-terminal

(ou pesquise / proc com o find etc.)

Andreas Frische
fonte
1
Observe que isso funciona com o ps do GNU (Linux), mas não com o ps do BSD.
21413 Josh
Isso está incorreto mesmo com o GNU ps. ps -C <command>corresponderá ao comando exato. Quando usado com os aou xopções ele irá informar todos os processos, pois ae xlista de processos , além do conjunto de processos correspondidos por outros meios.
Animism
@Animism True. Obrigado, eu consertei.
Andreas Frische
Isso funciona apenas se o nome do processo for especificado exatamente. Não funciona para uma correspondência parcial, por exemplo , logindpara systemd-logind, ou para combinar argumentos.
Acumenus 21/10
4

Mais uma alternativa :

ps -fC terminal

Aqui estão as opções:

 -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
fonte
6
Uma pequena desvantagem, e uma que não está realmente relacionada à pergunta do OP, é que isso não mostra coisas como o Tomcat, que na verdade é executado como java com uma lista de argumentos.
Charles Wood
-Copção já foi sugerida na resposta de @Andreas Frishe postada há mais de um ano e meio ...
Piotr Dobrogost
3

O uso de colchetes para colocar um caractere no padrão de pesquisa exclui o grepprocesso, pois ele não contém a regex correspondente.

$ 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
fonte
3

Disclaimer: Eu sou o autor desta ferramenta, mas ...

Eu usaria 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

Exceto por encontrar processos com uma interface de linha de comando sensata, ele também faz muitas outras coisas úteis, mais detalhes na página do projeto .

Funciona no Linux e OS X, facilmente instalado:

curl -Ls https://github.com/walles/px/raw/python/install.sh | bash
Johan Walles
fonte
0

Dependendo do caso de uso final, geralmente você prefere o Awk.

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

Isso é particularmente verdade quando você tem algo como

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

onde obviamente a regex pode ser fatorada no script Awk trivialmente:

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

Mas, realmente, não reinvente isso sozinho. pgrepe os amigos já existem há muito tempo e lidam com todo esse espaço problemático muito melhor do que a maioria das reimplementações ad hoc.

triplo
fonte
-2

Outra opção é editar seu .bash_profile(ou outro arquivo em que você mantém os aliases do bash) para criar uma função que recebe 'grep' dos resultados.

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

alias grep='mygrep'

O grep -v grepdeve ser o primeiro caso contrário, seu --color=autonão funcionará por algum motivo.

Isso funciona se você estiver usando o bash; se você estiver usando um shell YMMV diferente.

FlyingCodeMonkey
fonte
1
O que há com o alias e a função? Apenas faça function grep { command grep -v grep | command grep --color=auto "$@"; }(observe também a correção do argumento e a citação). No entanto, isso é interrompido porque qualquer não psinvocação de grepnão funcionará mais (os argumentos são passados ​​incorretamente). De qualquer forma, uma função muito mais útil seria aquela que modifica o regex para que ele não corresponda a si próprio, em vez de filtrar grepos grepresultados separadamente. E, é claro, inventar novas soluções para um problema que foi resolvido adequadamente décadas atrás não é muito produtivo.
tripleee