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 ...)

Steve Bennett
fonte

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
}
Noah Spurrier
fonte
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.
hmontoliu
fonte
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]

preso
fonte
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

ramruma
fonte
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
Steve Bennett
fonte
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.
blá
fonte
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