¿Cómo evitar que "ps" informe su propio proceso?

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

¿Hay alguna manera de evitar que se informe el último proceso (es decir, el grep que se inició al mismo tiempo que mi comando ps)?

(Comencé a tratar de encontrar una expresión regular que coincidiera con el literal pero no con el mismo, pero que parecía, um, no el enfoque correcto ...)

Steve Bennett
fuente

Respuestas:

14

Mi respuesta es una variación de la respuesta típica para buscar "foobar" en una pslista. El argumento de "-A" "ps"es más portátil que "aux", creo, pero este cambio es irrelevante para la respuesta. La respuesta típica se ve así:

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

En cambio, uso este patrón:

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

La principal ventaja es que es más fácil escribir scripts basados ​​en estos patrones porque simplemente concatena una cadena estática [^]]con cualquier patrón que esté buscando. No necesita quitar la primera letra de la cadena, luego insertarla entre las llaves cuadradas y luego concatenarla nuevamente. Al hacer scripts en shell, es más fácil simplemente pegarse [^]]frente al patrón que estaba buscando. Cortar cadenas en Bash es algo feo, por lo que mi variación lo evita. Esta variación dice mostrar las líneas donde el patrón coincide SIN un corchete derecho]. Dado que el patrón de búsqueda para excluir un corchete en realidad agrega el corchete al patrón, nunca coincidirá.

Entonces podría escribir un psgrepcomando portátil de la siguiente manera. Aquí, considero algunas diferencias entre Linux, OS X BSD y otros. Esto agrega los encabezados de columna de ps, proporciona un más personalizadopsel formato que mejor se adapta a mis necesidades, y muestra procesos que enumeran más, más ancho para que ninguno de los argumentos de la línea de comandos se pierda. Bueno, la mayoría no se pierden. Java es Java, a menudo hace las cosas de la peor manera posible, por lo que algunos servicios de Java superarán la longitud máxima permitida de argumentos de los que la tabla de procesos realizará un seguimiento. Creo que esto es 1024 caracteres. La longitud de comando único permitida para iniciar un proceso es mucho más larga, pero la tabla de proceso del núcleo no se molesta en realizar un seguimiento de nada de más de 1K de longitud. Una vez que se inicia el comando, el nombre del comando y la lista de argumentos no son necesarios, por lo que lo que se almacena en la tabla de procesos es solo 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
fuente
La desventaja es que esto realmente coincidirá con un carácter más (en frente) que el patrón original. Por ejemplo, esto nunca coincidirá con el PID. Y puede ser un poco engañoso cuando se usa con grep --colour.
Tonin
67

+1 para la respuesta concisa @jamzed, sin embargo, el OP podría necesitar alguna explicación:

ps | grep "[d]jango"

Usando esa expresión regular, está iniciando un proceso que su cadena ps no coincidirá, ya que la expresión regular coincide "django"y no "[d]jango". De esa forma, excluirá el proceso que tiene la cadena "[d] jango", que en este caso es grep; Lo mismo se puede aplicar a pgrep, egrep, awk, sed, etc., cualquier comando que haya utilizado para definir la expresión regular.

Desde man 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
fuente
2
Bueno. En realidad, estoy bastante cómodo con las expresiones regulares, pero no pude pensar de inmediato en una forma de evitar que la expresión regular coincida. El encerrar una letra entre corchetes tiene mucho sentido. (Incluir algo como [^!] También funcionaría ...)
Steve Bennett
1
Eso es bueno y astuto.
ceniza
Para el caso específico de 'ps', uso '[]' al frente del nombre del proceso que estoy buscando. Entonces no necesito analizar el nombre del proceso especialmente para la expresión regular, pero aún coincide.
Neromancer
@hmontoliu No funciona por ejemplo: ps aux | grep [s]cript1. ¿Podrías ayudar a comentar sobre la solución?
SOUser
@hmontoliu Mi culpa. Parece que la línea se muestra debido a las búsquedas anteriores ...
SOUser
30

ps | grep [d]jango

ps | grep d[j]ango

...

ps | grep djang[o]

atascado
fuente
Agregue espacio si necesita grep one char:ps aux| grep "[Z] "
AD
@jamzed No funciona, por ejemplo: ps aux | grep [s]cript1o ps aux | grep [s]cript2. La línea grep todavía se muestra. ¿Podrías ayudar a comentar sobre la solución?
SOUser
@jamzed Mi culpa. Parece que la línea se muestra debido a las búsquedas anteriores ...
SOUser
18

Use pgrep en su lugar: pgrep -lf django

ramruma
fuente
Como de costumbre, olvidé mencionar la plataforma (OS X en este caso). Presumiblemente, pgrep funciona en varios linuxes.
Steve Bennett
No estoy de acuerdo, @ramruma. Llegué a este hilo precisamente porque pgrepme da exactamente este problema. Pero debo decir que lo estoy probando en CygWin (donde psno se puede mostrar la línea de comando completa del proceso).
Sopalajo de Arrierez
El manual dice "El proceso pgrep o pkill en ejecución nunca se informará como una coincidencia", y de hecho no lo he visto hacerlo.
deltab
Acabo de estar lidiando con un problema en el que pensé que pgrepestaba coincidiendo. Resulta que coincidía con el nombre del basharchivo de script desde el que lo estaba ejecutando. Agregarlo lo -xarregló, luego coincide exactamente con el nombre del comando.
andynormancx
11

Oh espera, esto funciona:

ps | grep django | grep -v grep
Steve Bennett
fuente
77
Solo si la línea de comando del proceso no incluye legítimamente grep, con lo que no puede contar en el caso general.
un CVn
8

ps -d | grep django

del hombre ps:

 -d                  Lists information  about  all  processes
                     except session leaders.
paja
fuente
todavía muestra grep en la mía ...
Kevin
Sí, eso funciona para mí en OS X.
Steve Bennett
No funciona tan bien en Linux.
Acumenus
En términos más generales, las opciones psson notoriamente no portátiles, por lo que sin información sobre para qué plataforma es, esta respuesta no es muy útil. Además, esto obviamente no es adecuado cuando no está seguro de que el proceso que está buscando no sea un líder de proceso (es decir, esto puede ayudar si su objetivo es un demonio, pero generalmente no de otra manera).
tripleee
Curioso, en Mac esto parece mostrar solo el proceso grep y filtra todo lo demás.
Christopher Hunter