Como evitar que "ps" relate seu próprio processo?


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

Existe uma maneira de impedir que o último processo (ou seja, o grep iniciado ao mesmo tempo que o meu comando ps) seja relatado?

(Comecei a tentar criar uma regex que correspondesse ao literal, mas não ao próprio, mas que parecia, hum, não a abordagem correta ...)

Respostas:


14

Minha resposta é uma variação da resposta típica para procurar "foobar" em uma pslistagem. O argumento de "-A" "ps"é mais portátil do 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 ficar [^]]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 à direita]. Como o padrão de pesquisa para excluir um colchete, na verdade, adiciona o colchete ao padrão, ele nunca será correspondido.

Então você pode escrever um psgrepcomando portátil da seguinte maneira. Aqui, considero algumas diferenças entre Linux, OS X BSD e outros. Isso adiciona os cabeçalhos das colunas ps, fornece uma configuração mais personalizadapsformato que melhor se adapte às minhas necessidades e exibe processos que listam 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 argumentos e nomes de comandos não é necessária; portanto, o que é armazenado na tabela de processos é apenas informativo.

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
}

A desvantagem é que isso realmente corresponderá a um caractere a mais (na frente) do que o padrão original. Por exemplo, isso nunca corresponderá ao PID. E pode ser um pouco enganador quando usado com grep --colour.
Tonin

67

+1 para resposta concisa @jamzed, no entanto, o OP pode precisar de alguma explicação:

ps | grep "[d]jango"

Usando esse regex, você está iniciando um processo cuja sequência ps não corresponderá a si própria, uma vez que o regexp corresponde "django"e não "[d]jango". Dessa forma, você excluirá o processo que possui a string "[d] jango", que neste caso é grep; O mesmo pode ser aplicado ao pgrep, egrep, awk, sed, etc ... qualquer que seja o comando usado para definir o regex.

Do homem 7 regex

   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
Legal. Na verdade, estou bastante confortável com regexs, mas não consegui pensar imediatamente em uma maneira de impedir que o regexp se correspondesse. Colocar uma carta entre colchetes faz todo o sentido. (Incluindo algo como [^!] Também funcionaria ...)
Steve Bennett

11
Isso é legal e astuto.
cinzas

Para o caso específico de 'ps', uso '[]' na frente do nome do processo que estou procurando. Então não preciso analisar o nome do processo especialmente para a regex, mas ainda corresponde.
Neromancer

@hmontoliu Ele não funciona, por exemplo: ps aux | grep [s]cript1. Você poderia ajudar a comentar sobre a solução?
SOUser

@hmontoliu A culpa é minha. Parece que a linha é mostrada por causa das pesquisas anteriores ...
SOUser

30

ps | grep [d]jango

ps | grep d[j]ango

...

ps | grep djang[o]


Adicione espaço se você precisar grep um caractere:ps aux| grep "[Z] "
5/06/15 AD

@jamzed Não funciona, por exemplo: ps aux | grep [s]cript1ou ps aux | grep [s]cript2. A linha grep ainda é mostrada. Você poderia ajudar a comentar sobre a solução?
SOUser

@jamzed Minha culpa. Parece que a linha é mostrada por causa das pesquisas anteriores ...
SOUser

18

Use pgrep: pgrep -lf django


Como sempre, eu esqueci de mencionar a plataforma (OS X neste caso). Presumivelmente, o pgrep funciona em vários linuxes.
Steve Bennett

Eu não concordo, @ramruma. Eu vim para este segmento precisamente porque pgrepme dá exatamente esse problema. Mas devo dizer que estou testando no CygWin (onde psnão é possível mostrar a linha de comando completa do processo).
Sopalajo de Arrierez 04/04

O manual declara "O processo em execução pgrep ou pkill nunca se reportará como uma correspondência." E, na verdade, eu não o vi fazer isso.
Deltab # 7/16

Acabei de lidar com um problema em que pensei que pgrepestava se combinando. Acontece que ele estava correspondendo ao nome do basharquivo de script do qual estava sendo executado. Adicionando -xcorrigido, então ele faz uma correspondência exata no nome do comando.
andynormancx 14/03

11

Oh espera, isso funciona:

ps | grep django | grep -v grep

7
Somente se a linha de comando do processo não incluir legitimamente grep, com a qual você não pode contar no caso geral.
a CVn

8

ps -d | grep django

do homem ps:

 -d                  Lists information  about  all  processes
                     except session leaders.

mostra ainda grep na minha ...
Kevin

Sim, isso funciona para mim no OS X.
Steve Bennett

Não funciona tão bem no Linux.
Acumenus 18/08/14

De um modo mais geral, as opções pssão notoriamente não portáveis; portanto, sem informações sobre qual plataforma é, essa resposta não é muito útil. Além disso, isso obviamente não é adequado quando você não tem certeza de que o processo que você está procurando não é um líder de processo (ou seja, isso pode ajudar se seu destino for um daemon, mas geralmente não o contrário).
Tripleee

Engraçado, no Mac, isso parece mostrar apenas o processo grep e filtra todo o resto.
Christopher Hunter
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.