¿Cómo puedo evitar que aparezca 'grep' en los resultados de ps?

304

Cuando busco algún proceso que no existe, por ejemplo

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

Obviamente no me importa el grep, ¡eso tiene tanto sentido como buscar el psproceso!

¿Cómo puedo evitar que grep aparezca en los resultados?

Wayne Werner
fuente
28
Si solo necesita el PID de un proceso, puede reemplazarlo ps aux |grepcon pgrep(o pgrep -f).
jofel
66
La misma pregunta en Serverfault y de superusuario .
Thor
¿Es legítimo ese resultado? parece que NO hay ningún programa llamado fnord corriendo ...
acólito
44
@acolyte, eso es precisamente, pero como está canalizando la salida en grep, grep se está ejecutando (esperando la salida de ps aux, espero). Entonces, la pregunta es cómo evitar grep fnordque aparezca como un proceso en ejecución porque obviamente no estoy interesado en ese .
Wayne Werner
2
@acolyte no es una sorpresa que no puedas ver la línea "fnord". No se supone que puedas verlo. Si le sobran unos 2 o 3 minutos, búsquelo.
Francesco

Respuestas:

438

Resulta que hay una solución encontrada en llavero .

$ ps aux | grep "[f]nord"

Al poner los corchetes alrededor de la letra y las comillas alrededor de la cadena, busca la expresión regular, que dice: "Encuentra el carácter 'f' seguido de 'nord'".

Pero dado que coloca los corchetes en el patrón 'f' ahora va seguido de ']', por greplo que no aparecerá en la lista de resultados. Neato!

Wayne Werner
fuente
26
@acolyte: La salida de ps incluirá una línea que termina con grep [f]nord. Sin embargo, esa línea no entrará a través del filtro grep, porque la cadena [f]nordno coincide con la expresión regular [f]nord.
LarsH
99
@LarsH interesante, gracias! habría sugerido ps aux | grep fnord | grep -v grep... lo que parece haber sido sugerido por algunas personas ... jajaja
acólito
55
@progo Sí, necesita citar [incluso en bash. Pruébelo con un archivo llamado fnorden el directorio actual.
Gilles
26
Grepping la salida de pspuede ser un viejo truco, pero no es confiable. Usarpgrep si está disponible.
Gilles
99
@naxa Imagine que tiene una llamada de programa fnordy un programa llamado safnorde. O hay un usuario llamado bfnord, y terminas matando todos sus procesos. Etc.
Gilles
165

Otra opción que uso (especialmente para ver si se está ejecutando un proceso) es el pgrep comando. Esto buscará un proceso de coincidencia, pero no mostrará una línea grep para la búsqueda. Me gusta porque es una forma rápida de búsqueda, sin regexing ni escapar de nada.

pgrep fnord
BriGuy
fuente
8
Querrán que la -fopción sea más parecida ps | grep.
jordanm
@jordanm En realidad, pgrep -fse verá más como ps -f | grep.
michelpm
55
También existe el -largumento para hacer que muestre el comando que se está haciendo coincidir.
Patrick
15
ps | grep '[f]nord'es inteligente y venerable, pero pgrep tiene razón .
kojiro
3
Siempre puede hacerlo ps $(pgrep cmd) ...si a `pgrep le faltan opciones (aunque no funcionará para un conjunto de comandos vacío).
Maciej Piechotka
63

La solución ideal es la presentada por BriGuy

pgrep fnord 

Pero si no desea hacer eso, puede excluir todas las líneas que coinciden con grep con:

ps aux | grep -v grep | grep "fnord"
RSFalcon7
fuente
77
pero ¿qué pasa si la línea que estoy buscando es "bash bash grep bash"?
Sparr
1
@Sparr Entonces deberías usar la mejor solución: pgrepo encontrar otra;)
RSFalcon7
Tenga cuidado con el límite de longitud del nombre con pgrep. Use -f para obtener el nombre completo de la ruta o puede encontrar que sus coincidencias fallan con nombres más largos. -Yo también es bueno enumerar los partidos
Neil McGill
24

No es la solución más elegante, pero podría hacer esto:

$ ps aux | grep fnord | grep -v grep

Brandon Kreisel
fuente
Es mala respuesta! Porque si hubiera una palabra grepen tu frase. No mostrará ese proceso. Por ejemplo, suponga que foo_grep_bar.txtel nanocomando está editando un archivo llamado . Entonces, hay un proceso en ejecución: de root 14908 0.0 0.0 110012 1692 pts / 3 S + Oct31 0:00 nano foo_grep_bar.txtacuerdo con esta respuesta, esto no funcionará: $ ps aux | grep nano | grep -v grepporque hay una palabra clave en su nombre de archivo.
Nabi KAZ el
Prefiero esto porque es más explícito sobre su intención que la respuesta aceptada y funciona en todos los casos menos uno.
samaspin
1
según superuser.com/a/409658/450260 , debe excluir el completo, grep fnordno solo, grepes decir $ ps aux | grep fnord | grep -v "grep fnord"
Davos
14

En zsh, grep fnord =(ps aux).

La idea es, primero ejecutar ps aux, poner el resultado en un archivo, luego usarlo grepen ese archivo. Solo que no tenemos un archivo, ya que usamos la "sustitución de proceso" de zsh.

Para ilustrar, intente

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

El resultado debería ser el mismo.

Comentario general sobre algunas de las otras respuestas. Algunos son muy complicados y / o largos de escribir. No es solo una cuestión de tener razón, también debe ser utilizable. Pero eso no significa que algunas de esas soluciones sean malas; solo, deben estar envueltos dentro de una mini interfaz de usuario para que sean utilizables.

Emanuel Berg
fuente
1
Sin conocer la sustitución de procesos de zsh, pero ¿es seguro que los dos procesos se llaman uno después del otro y no en paralelo?
Paŭlo Ebermann
3
@ PaŭloEbermann: Para el paralelo es el <(command). grep grep =(ps aux)No muestra ninguna línea.
Maciej Piechotka
Zsh también puede "igualar" la salida de ps. print -l ${(M)${(f)¨$(ps aux)¨}:#*fnord*}
Friartek
6
ps aux | grep $(echo fnord | sed "s/^\(.\)/[\1]/g")
yPhil
fuente
3
esto parece un IOCCC, pero para la línea de comandos de Unix en lugar de C ^^ ¿No | grep $(echo fnord)fue suficiente? ¿también le pide a sed que busque y reemplace cada carácter en "fnord" por su propio valor? ^^ felicidades. Apuesto a que puedo hacer uno aún más largo, pero probablemente no será tan divertido ^^
Olivier Dulac
1
Me disculpo porque el tono de mi comentario anterior puede sonar ofensivo (y no puedo editarlo después de 5 minutos) ... Su respuesta fue realmente una lectura alegre, y no estaba tratando de hacerte quedar mal. Realmente creo que lo hiciste así a propósito ^^
Olivier Dulac
1
No te disculpes, tu respuesta fue muy divertida de leer (y acertada también). Quise decir pgrep -l $ 1 de todos modos;)
yPhil
3
@ OlivierDulac: Él no solo reemplaza el primer personaje con su propio valor; lo reemplaza con la concatenación de su valor entre corchetes. (Esos corchetes no son especiales, son literales). Básicamente, él está generalizando sobre la respuesta de Wayne Werner, de modo que el proceso de poner corchetes alrededor del primer personaje puede ser escrito. +1
LarsH
2
ps aux | grep '[^]]fnord'evitaría eso gimnástico.
Stéphane Chazelas
6

Esta respuesta es específica de GNU . Vea la respuesta de Wayne para una solución más general.

Buscando procesos

Si solo está buscando fnordprocesos, puede usar la -Copción para seleccionar por nombre de comando:

ps -C fnord

Esto se puede mezclar con las opciones de formato de estilo BSD y POSIX a su gusto. Consulte la página de manual de ps para obtener una lista completa.

¿Buscando algo más?

Si necesita algo más avanzado que una búsqueda exacta de un nombre de comando, ¡no pierda la esperanza! Esto todavía se puede hacer en el pslado de la tubería. Todo lo que tenemos que hacer es decirle psque excluya grepprocesos del resultado:

ps -NC grep | grep 'fnord'

-C grepselecciona todos los procesos grep y -Nniega la selección. Esto se puede usar para buscar argumentos de comando, parte del nombre de un comando o expresiones regulares más complejas.

Morgan
fuente
1
Esto es bueno con GNU pspero -CPOSIX no lo especifica y tiene un significado completamente diferente en BSD
Eric Renouf
Realmente es un fastidio, no hay BSD equivalente (lo que también significa que no funcionará en una Mac). Usar ps-C es, con mucho, la respuesta más simple de cualquiera de estas.
Christopher Hunter
3

Mi respuesta es una variación de la respuesta típica para buscar "foobar" en una lista 'ps'. 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 pegar "[^]]" delante del 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 comando portátil 'psgrep' 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 formato 'ps' más personalizado que se adapta mejor 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

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
2

La forma más simple de hacer esto sin agnóstico sería almacenarlo primero en una variable:

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

Llamada: la grep fnord =(ps aux)respuesta de @ EmanuelBerg es, con mucho, la más elegante, aunque requiere zsh. Lo tuve brevemente en mis archivos rc, pero bash se queja de esa sintaxis incluso a pesar de una condicional que debería evitar su evaluación.


De mis archivos rc, tengo una versión que no distingue entre mayúsculas y minúsculas que toma los argumentos de grep:

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

Paseo de código, una viñeta por línea de código:

  • Capture la pssalida detallada (en una localvariable para que desaparezca cuando la función regrese)
  • Muestre la primera línea (el título) en error estándar para que los resultados se puedan filtrar aún más sin afectar el título. La sustitución dice: tomar $PS_OUTPUTy eliminar todo después del primer avance de línea (regex equiv:) s/\n.*$//msg. Esto nos impide agarrar el título
  • Muestre la pssalida con todo excepto la primera línea (regex equiv:) s/^.*\n//my grep su contenido con -imayúsculas y minúsculas y con todos los argumentos entregados a esta función (en el caso de no argumentos ^, que coincide con el inicio de cualquier línea para que coincida todo)
Adam Katz
fuente
1

Aquí hay una versión extendida de la grep -v grepsolución, filtrando todos los grepprocesos que no se han estado ejecutando por más de un segundo, lo cual es una mejora sobre "simplemente descartar todas las ocurrencias de grep".

$ ps -ef | grep -vw "00:00:00 grep" | grep <searchTerm>

respectivamente

$ ps aux | grep -vw "0:00 grep" | grep <searchTerm>

Esto puede no ser portátil y depende del formato de salida real de su pscomando local .

Es posible que desee combinar esto con una grepsalida en color para mayor comodidad:

$ alias grep='grep --color=auto'
Murphy
fuente
0

Tal vez es hora de usar una secuencia real esta vez. El uso de tuberías lo hace paralelo.

ps aux >f && grep tmpfs <f

Feo porque habrá un archivo f, pero no es mi culpa que no haya una sintaxis para procesos secuenciales en los que aún desee utilizar la salida de un proceso ejecutado anteriormente.

Sugerencia para la sintaxis de un operador secuencial:

ps aux ||| grep tmpfs
Anne van Rossum
fuente
La incapacidad de la gente común para filtrar fácilmente una secuencia no es una razón para que la élite se base en secuencias. Sería un paso atrás en informática.
Acumenus
@ABB en.wikipedia.org/wiki/Communicating_sequential_processes tienen muchos más operadores que los que terminaron en el shell Thompson. Podría haber habido un operador que sea secuencial y que comunicara su resultado al siguiente proceso de la secuencia tan pronto como salga. Un "paso atrás en la informática" al proporcionar un operador adicional parece un poco duro.
Anne van Rossum
Buen enlace, pero, por supuesto, el procesamiento secuencial es peor tanto en el uso de CPU como de memoria (o disco), en relación con el procesamiento paralelo. En este caso, si primero debo almacenar toda la pssalida antes que yo grep, estoy usando más memoria (o disco) por más tiempo.
Acumenus
0

El comando pgrep, como han dicho otros, devolverá el PID (ID de proceso) de los procesos en función del nombre y otros atributos. Por ejemplo,

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

le dará los PID, delimitados por una coma (,) de todos los procesos cuyo nombre coincide con el que ejecuta el usuario <username>. Puede usar el modificador -x antes para devolver solo coincidencias exactas.

Si desea obtener más información sobre estos procesos (como implica la ejecución de las opciones auxiliares desde ps), puede usar la opción -p con ps, que coincide en función del PID. Así por ejemplo,

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

proporcionará información detallada de todos los PID coincidentes con el comando pgrep.

eToThePiIPower
fuente
psfalla si pgrepdevuelve un conjunto vacío. Tengo una respuesta que se basa en la suya y trata de abordar este problema.
Acumenus
0

Aquí hay un ejemplo simple para encontrar el PID del ssh-agentnombre de usuario sin mostrar el PID del grepproceso en sí:

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

Si desea, por ejemplo, matar ssh-agentpara el usuario actual, puede usar el siguiente comando:

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

Para crear un práctico alias, agregue a su archivo ~ / .bashrc o ~ / .zshrc el siguiente código:

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

Y para usar el alias aquí hay ejemplos para obligar a todos a aprender expresiones regulares:

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

PD: solo he probado estos comandos en Ubuntu y Gentoo.

Constantin Zagorsky
fuente
(1) La pregunta no dice que el usuario está buscando uno de sus propios procesos; es posible que el usuario no conozca al propietario del proceso que está buscando. (2) Tan elegante como es esta respuesta, todavía fallaría si hubieras dicho "${USER}.* /usr/bin/ssh-agent". Funciona porque dijiste [ ]; es decir, solo está utilizando el mecanismo de la respuesta aceptada. Es lo mismo que bien grep "[s]sh-agent".
G-Man
Tienes razón. (1) Compartí lo que podría ser útil ya que me encontraba frente a esta página de vez en cuando (2) Sí, utilicé la expresión regular como en la respuesta aceptada. (3) Actualicé mi respuesta para que sea la misma que la aceptada, ya que la respuesta es mejor, pero también mostré cómo hacer y alias para usar con el nombre de usuario proporcionado o sin él. (4) También se muestra cómo definir la función, aunque no es necesario pero funciona de manera interesante ya que $ 1 y $ 2 no se superponen. Thx # G-Man
Constantin Zagorsky
-1

Usar la opción -x (coincidencia exacta) funcionó para mí. Lo combiné con -f (línea de comando completa), para poder hacer coincidir mi proceso precisamente con:

pgrep -x -f "path_i_used_when_starting/cmd params_i_used"
humor
fuente
¿Quienquiera que esté haciendo el voto negativo en auto se explicará? Esto ha estado funcionando para resolver este problema para mí sin falta durante años.
moodboom
-3

Puedes hacerlo fácilmente, solo definiendo un ALIAS en tu .bashrc estilo:

alias grep='grep -v grep | grep'
Keivan Beigi
fuente
No estoy seguro de quién votó en contra o por qué, pero esto le permite utilizar el uso completo de ps que pgrep no.
opticyclic
1
No solo que esto excluye inadvertidamente otros procesos grep; También interrumpe el grepuso en otros casos. Tratar echo I love grep | grep love.
trosos
@trosos Casi 11 años he estado * nix-ing ... y nunca he usado ese patrón ... quizás el año que viene, quién sabe.
a20