Como posso impedir que o 'grep' apareça nos resultados do ps?

304

Quando procuro algum processo que não existe, por exemplo,

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

Obviamente, eu não ligo para grep - isso faz tanto sentido quanto procurar pelo psprocesso!

Como posso impedir que o grep apareça nos resultados?

Wayne Werner
fonte
28
Se você precisar apenas do PID de um processo, poderá substituí-lo ps aux |greppor pgrep(ou pgrep -f).
Jofel
6
Mesma pergunta no Serverfault e Superuser .
Thor
essa saída é legítima? parece que não há um programa chamado fnord correndo ...
acólito
4
@acolyte, é exatamente isso - mas porque está canalizando a saída para o grep, o grep está em execução (aguardando a saída de ps aux, espero). Portanto, a questão é como impedir grep fnordque apareça como um processo em execução, porque obviamente não estou interessado nisso .
Wayne Werner
2
@acolyte não é uma surpresa que você não consiga ver a linha "fnord". Você não deveria poder vê-lo. Se você tiver 2 ou 3 minutos de sobra, procure-o.
Francesco

Respostas:

439

Acontece que há uma solução encontrada no chaveiro .

$ ps aux | grep "[f]nord"

Ao colocar os colchetes em volta da letra e das aspas, você procura a regex, que diz: "Encontre o caractere 'f' seguido de 'nord'".

Mas como você coloca os colchetes no padrão 'f' agora é seguido por ']', grepnão será exibido na lista de resultados. Neato!

Wayne Werner
fonte
26
@acolyte: A saída do ps incluirá uma linha que termina com grep [f]nord. No entanto, essa linha não entra no filtro grep, porque a string [f]nordnão corresponde à expressão regular [f]nord.
precisa saber é
9
@ LarsH interessante, obrigado! i teria sugerido ps aux | grep fnord | grep -v grep... que parece já ter sido sugerido por algumas pessoas ... lol
acólito
5
@progo Sim, você precisa citar o [even in bash. Experimente com um arquivo chamado fnordno diretório atual.
Gilles
25
Grepping a saída de pspode ser um truque antigo, mas não é confiável. Usepgrep se disponível.
Gilles
8
@naxa Imagine que você tenha uma chamada de programa fnorde um programa chamado safnorde. Ou existe um usuário chamado bfnord, e você acaba matando todos os processos dele. Etc.
Gilles
164

Outra opção que eu uso (especialmente apenas para verificar se um processo está em execução) é o pgrep comando Isso procurará um processo de correspondência, mas não listará uma linha grep para a pesquisa. Gosto porque é uma maneira rápida de pesquisar, sem regexar ou escapar de nada.

pgrep fnord
BriGuy
fonte
8
Eles querem que a -fopção seja mais parecida ps | grep.
Jordanm #
@jordanm Na verdade, pgrep -fserá mais parecido ps -f | grep.
Michelpm
5
Há também o -largumento para mostrar o comando que está sendo correspondido.
Patrick
15
ps | grep '[f]nord'é inteligente e venerável, mas o pgrep está certo .
Kojiro #
3
Você sempre pode fazer ps $(pgrep cmd) ...se o `pgrep estiver faltando opções (embora não funcione para um conjunto vazio de comandos).
Maciej Piechotka
62

A solução ideal é a apresentada pela BriGuy

pgrep fnord 

Mas se você não quiser fazer isso, poderá excluir todas as linhas que correspondem ao grep com:

ps aux | grep -v grep | grep "fnord"
RSFalcon7
fonte
7
mas e se a linha que estou procurando for "bash bash grep bash"?
Sparr
1
@Sparr Em seguida, você deve usar a melhor solução: pgrepou encontrar outro;)
RSFalcon7
Cuidado com o limite de tamanho de nome com pgrep. Use -f para obter o nome do caminho completo ou poderá encontrar falhas nas correspondências com nomes mais longos. -l também é bom listar as partidas
Neil McGill
25

Não é a solução mais elegante, mas você pode fazer isso:

$ ps aux | grep fnord | grep -v grep

Brandon Kreisel
fonte
É uma resposta ruim! Porque se houvesse uma palavra grepem sua frase. Não mostrará esse processo. Por exemplo, suponha que um arquivo chamado foo_grep_bar.txtesteja sendo editado pelo nanocomando. Portanto, há um processo em execução: de root 14908 0.0 0.0 110012 1692 pts / 3 S + Oct31 0:00 nano foo_grep_bar.txtacordo com esta resposta, isso não funcionará: $ ps aux | grep nano | grep -v grepporque há uma palavra grep no seu nome de arquivo.
Nabi KAZ
Prefiro isso como mais explícito sobre sua intenção do que a resposta aceita e funciona em todos os casos, exceto um.
samaspin 28/03
1
de acordo com superuser.com/a/409658/450260, você deve excluir o total, grep fnordnão apenas grepisto é, # $ ps aux | grep fnord | grep -v "grep fnord"
1005 Davos
15

No zsh grep fnord =(ps aux),.

A idéia é, primeiro executar ps aux, colocar o resultado em um arquivo e depois usá grep-lo. Apenas não temos um arquivo, pois usamos a "substituição de processo" do zsh.

Para ilustrar, tente

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

O resultado deve ser o mesmo.

Comentário geral sobre algumas das outras respostas. Alguns são muito complicados e / ou demoram para digitar. Não é apenas uma questão de estar certa, deve ser utilizável também. Mas isso não significa que algumas dessas soluções sejam ruins; somente, eles devem ser agrupados em uma mini-interface do usuário para torná-los utilizáveis.

Emanuel Berg
fonte
1
Não conhecendo a substituição de processos do zsh, mas é certo que os dois processos são chamados um após o outro e não em paralelo?
Paŭlo Ebermann
3
@ PaŭloEbermann: Para paralelo é o <(command). grep grep =(ps aux)não mostra nenhuma linha.
Maciej Piechotka
Zsh também pode "combinar" a saída do ps. print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
Friartek
7
ps aux | grep $(echo fnord | sed "s/^\(.\)/[\1]/g")
yPhil
fonte
3
isso parece um IOCCC, mas para a linha de comando unix em vez de C ^^ Simplesmente | grep $(echo fnord)não foi suficiente? você também pede ao sed para pesquisar e substituir cada caractere em "fnord" por seu próprio valor? ^^ parabéns. Aposto que posso fazer até mais longo, mas provavelmente não será tão engraçado ^^
Olivier Dulac
1
Peço desculpas porque o tom do meu comentário acima pode parecer ofensivo (e não posso editá-lo após cinco minutos) ... Sua resposta foi realmente uma leitura alegre e eu não estava tentando fazer você parecer mal. Eu realmente acho que você fez isso assim de propósito ^^
Olivier Dulac
1
Não peça desculpas, sua resposta foi realmente divertida de ler (e também diretamente). Eu quis dizer pgrep -l $ 1 de qualquer maneira;)
yPhil
3
@OlivierDulac: Ele não substitui apenas o primeiro caractere por seu próprio valor; ele o substitui pela concatenação de seu valor entre colchetes. (Esses colchetes não são especiais, são literais.) Basicamente, ele está generalizando a resposta de Wayne Werner, para que o processo de colocar colchetes ao redor do primeiro caractere possa ser roteirizado. 1
LarsH
2
ps aux | grep '[^]]fnord'evitaria essa ginástica.
Stéphane Chazelas
6

Essa resposta é específico do GNU . Veja a resposta de Wayne para uma solução mais geral.

Procurando por Processos

Se você está apenas procurando fnordprocessos, pode usar a -Copção para selecionar pelo nome do comando:

ps -C fnord

Isso pode ser combinado com as opções de formato no estilo BSD e POSIX ao seu gosto. Veja a página de manual do ps para uma lista completa.

Procurando algo mais?

Se você precisar de algo mais avançado do que uma busca exata por um nome de comando, não perca a esperança! Isso ainda pode ser feito na pslateral do tubo. Tudo o que precisamos fazer é dizer pspara excluir grepprocessos do resultado:

ps -NC grep | grep 'fnord'

-C grepseleciona todos os processos grep e -Nnega a seleção. Isso pode ser usado para procurar argumentos de comando, parte de um nome de comando ou expressões regulares mais complexas.

Morgan
fonte
1
Isso é bom com GNU ps, mas -Cnão é especificado por POSIX e tem aa significado completamente diferente em BSD
Eric Renouf
É realmente uma chatice, não há equivalente BSD (o que também significa que não funcionará em um Mac). Usar ps -C é de longe a resposta mais simples de qualquer uma delas.
9138 Christopher Hunter
3

Minha resposta é uma variação da resposta típica para procurar "foobar" em uma lista de 'ps'. O argumento de "-A" "ps" é mais portátil que "aux", acredito, mas essa mudança é irrelevante para a resposta. A resposta típica é assim:

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

Em vez disso, uso este padrão:

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

A principal vantagem é que é mais fácil escrever scripts com base nesses padrões, porque você simplesmente concatena uma sequência estática "[^]]" com qualquer padrão que esteja procurando. Você não precisa retirar a primeira letra da string, depois inseri-la entre os colchetes e concatenar isso novamente. Ao criar scripts no shell, é mais fácil colocar "[^]]" na frente do padrão que você estava procurando. Fatiar cordas no Bash é uma coisa feia, então minha variação evita isso. Essa variação indica as linhas em que o padrão corresponde SEM um colchete quadrado direito]. Como o padrão de pesquisa para excluir um colchete, na verdade, adiciona o colchete ao padrão, ele nunca será compatível.

Então você pode escrever um comando portátil 'psgrep' da seguinte maneira. Aqui, considero algumas diferenças entre Linux, OS X BSD e outros. Isso adiciona os cabeçalhos das colunas de 'ps', fornece um formato 'ps' mais personalizado, adequado às minhas necessidades, e exibe processos listando extra, extra largo, para que nenhum dos argumentos da linha de comando seja esquecido. Bem, a maioria não faz falta. Java sendo Java, geralmente faz as coisas da pior maneira possível; portanto, alguns serviços java executam o comprimento máximo permitido de argumentos que a tabela de processos acompanhará. Acredito que sejam 1024 caracteres. O tamanho do comando único que é permitido iniciar um processo é muito mais longo, mas a tabela de processos do kernel não se preocupa em rastrear algo com mais de 1K de comprimento. Depois que o comando é iniciado, a lista de nome e argumento do comando não é mais '

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
}
Noah Spurrier
fonte
2

A maneira mais simples, independente do shell, de fazer isso seria armazená-lo em uma variável primeiro:

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

Texto explicativo: A grep fnord =(ps aux)resposta de @ EmanuelBerg é de longe a mais elegante, embora exija zsh. Eu o tive brevemente nos meus arquivos rc, mas o bash reclama dessa sintaxe, apesar de um condicional que deve impedir sua avaliação.


Nos meus arquivos rc, tenho uma versão que não diferencia maiúsculas de minúsculas que aceita os argumentos do grep:

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

Caminhada pelo código, um marcador por linha de código:

  • Capture a pssaída detalhada (em uma localvariável para que ela desapareça quando a função retornar)
  • Exiba a primeira linha (o título) com erro padrão para que os resultados possam ser filtrados ainda mais sem afetar o título. A substituição diz: pegue $PS_OUTPUTe remova tudo após o primeiro avanço de linha (regex equiv:) s/\n.*$//msg. Isso nos impede de cumprimentar o título
  • Exiba a pssaída com tudo, exceto a primeira linha (regex equiv s/^.*\n//m:), e grep seu conteúdo com -ifor case-insensitive e com todos os argumentos entregues a essa função (no caso de sem argumentos ^, que corresponde ao início de qualquer linha para corresponder) tudo)
Adam Katz
fonte
1

Talvez seja hora de usar uma sequência real desta vez. O uso de tubos torna paralelo.

ps aux >f && grep tmpfs <f

Feio porque haverá um arquivo f, mas não é minha culpa que não haja sintaxe para processos sequenciais em que você ainda deseja usar a saída de um processo executado anteriormente.

Sugestão para a sintaxe de um operador seqüencial:

ps aux ||| grep tmpfs
Anne van Rossum
fonte
A incapacidade das pessoas comuns de filtrar facilmente um fluxo dificilmente é uma razão para a elite se basear em sequências. Seria um passo atrás na computação.
Acumenus 18/08/14
O @ABB en.wikipedia.org/wiki/Communicating_sequential_processes possui muito mais operadores do que aqueles que terminaram no shell Thompson. Poderia ter havido um operador seqüencial e que comunicou seu resultado ao próximo processo na sequência assim que sua saída. Um "retrocesso na computação", fornecendo um operador adicional, parece um pouco duro.
Anne van Rossum
Link legal, mas é claro que o processamento seqüencial é pior no uso da CPU e da memória (ou disco) - em relação ao processamento paralelo. Nesse caso, se primeiro devo armazenar toda a pssaída antes de grepusar mais memória (ou disco) por mais tempo.
Acumenus
0

O comando pgrep, como outros já declararam, retornará o PID (ID do processo) dos processos com base no nome e outros atributos. Por exemplo,

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

fornecerá os PIDs, delimitados por vírgula (,) de todos os processos cujo nome corresponde à execução do usuário <username>. Você pode usar a opção -x antes para retornar apenas correspondências exatas.

Se você deseja obter mais informações sobre esses processos (como implica a execução das opções aux do ps), você pode usar a opção -p com ps, que corresponde com base no PID. Então, por exemplo,

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

fornecerá informações detalhadas de todos os PIDs correspondentes ao comando pgrep.

eToThePiIPower
fonte
psfalhará se pgrepretornar um conjunto vazio. Tenho uma resposta que se baseia na sua e tenta resolver esse problema.
Acumenus
0

Aqui está um exemplo simples para encontrar o PID do ssh-agentnome de usuário sem mostrar o PID do greppróprio processo:

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

Se você deseja, por exemplo, matar ssh-agento usuário atual, pode usar o seguinte comando:

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

Para criar um alias útil, adicione ao seu arquivo ~ / .bashrc ou ~ / .zshrc o seguinte código:

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

E para usar o alias, aqui estão exemplos para forçar todos a aprender expressões regulares:

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

PS: Apenas testei esses comandos no Ubuntu e Gentoo.

Constantin Zagorsky
fonte
(1) A pergunta não diz que o usuário está procurando um de seus próprios processos - o usuário pode não conhecer o proprietário do processo que está procurando. (2) Por mais sofisticada que seja essa resposta, ela ainda falharia se você tivesse dito "${USER}.* /usr/bin/ssh-agent". Funciona porque você disse [ ]; ou seja, você está apenas usando o mecanismo da resposta aceita. Você pode muito bem grep "[s]sh-agent".
G-Man
Você está certo. (1) compartilhei o que poderia ser útil, pois me encontrava de frente para esta página de vez em quando (2) Sim, eu usava expressão regular como resposta aceita. (3) Atualizei minha resposta para ser a mesma que a aceita, mas também mostrei como criar um apelido para ser usado com o nome de usuário fornecido ou sem ele. (4) Também é mostrado como definir função, embora não seja necessário, mas funcione de maneira interessante, pois $ 1 e $ 2 não se sobrepõem. Thx # G-Man
Constantin Zagorsky
-1

Você pode fazer isso facilmente, apenas definindo um ALIAS .bashrc como este:

alias grep='grep -v grep | grep'
Keivan Beigi
fonte
Não tenho certeza de quem votou menos ou por quê, mas isso permite que você use o uso completo do ps que o pgrep não.
Opticyclic #
Não apenas isso exclui inadvertidamente outros processos grep; também interrompe o grepuso em outros casos. Tente echo I love grep | grep love.
trosos
@trosos Quase 11 anos estive * nix-ing .. e nunca usei esse padrão ... talvez no próximo ano - quem sabe o que é certo.
a20 29/03
-1

Usar a opção -x (correspondência exata) funcionou para mim. Combinei com -f (linha de comando completa), para que eu pudesse combinar meu processo precisamente com:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"
humor
fonte
Quem vai fazer o downvoting drive-by explicar-se? Isso vem trabalhando para resolver esse problema para mim sem falhas há anos.
moodboom 13/04