Cómo grep ps salida con encabezados

26

¿Cómo puedo grep la salida PS con los encabezados en su lugar?

Estos dos procesos forman una aplicación que se ejecuta en mi servidor ...

root     17123 16727  0 16:25 pts/6    00:00:00 grep GMC
root     32017     1 83 May03 ?        6-22:01:17 /scripts/GMC/PNetT-5.1-SP1/PNetTNetServer.bin -tempdir /usr/local/GMC/PNetT-5.1-SP1/tmpData -D

¿ 6-22:01:17significa que ha estado funcionando durante 6 días? Estoy tratando de determinar la duración de cuánto tiempo se ha estado ejecutando el proceso ...

¿Es la segunda columna la identificación del proceso? Entonces, si lo hago kill 32017, ¿matará el segundo proceso?

Webnet
fuente

Respuestas:

37
ps -ef | egrep "GMC|PID"

Reemplace el "GMC" y pscambie según sea necesario.

Salida de ejemplo:

root@xxxxx:~$ ps -ef | egrep "disk|PID"

UID        PID  PPID  C STIME TTY          TIME CMD
paremh1  12501 12466  0 18:31 pts/1    00:00:00 egrep disk|PID
root     14936     1  0 Apr26 ?        00:02:11 /usr/lib/udisks/udisks-daemon
root     14937 14936  0 Apr26 ?        00:00:03 udisks-daemon: not polling any devices
Hippy
fuente
8
Sería bueno agregar alguna información sobre 'por qué' esto funciona.
Elijah Lynn el
2
No, eso es un ejercicio para el usuario.
Hyppy
@ElijahLynn Coincide con el texto en el encabezado, en este caso, PID. Pero podría cambiarlo por UID, PTIME o cualquier otra cosa en el encabezado ...
Ben Creasy
55
Por lo tanto, ps -eselecciona todos los procesos y ps -fes una lista de formato completo que muestra los encabezados de las columnas. Luego canalizamos los encabezados de columna y la salida a egrep, que es grep extendido y permite que la tubería |tenga un significado especial, que es OR (esto O aquello). Por lo tanto, termina haciendo coincidir el PID en los encabezados de columna más las líneas de salida que importan.
Elijah Lynn
Tuve que usar comillas simples en el comando egrep / grep -E en Ubuntu 16.04, por ejemplo: ps -ef | grep -E 'GMC|PID'
Vlax
13

Gracias a geekosaur, me gustaría usar este comando para sus demandas, en lugar de un comando separado:

ps -ef | head -1; ps -ef | grep "your-pattern-goes-here"

Lo complicado es hacer uso de ";" compatible con el shell para encadenar el comando.

Vic Lau
fuente
Esto es más limpio y más robusto que la respuesta aceptada. No afirma que el encabezado tenga PID y no agrega complejidad a la cadena grep.
7yl4r
2
oh espera ... tienes el ps -efrepetido. aún mejor esps -ef | { head -1 ; grep "your-pattern" ; }
7yl4r
@ 7yl4r nunca usó esa habilidad de caparazón. Probé tu comando mejorado, ¡funciona perfectamente! Tienes aprendió, :)
Vic Lau
3
Explicación encontrada sobre esta técnica, llamada 'Comandos de agrupación', para curiosidad de otros, consulte: gnu.org/software/bash/manual/html_node/Command-Grouping.html
Vic Lau
@ 7yl4r gran técnica! Estaba buscando cómo no repetir el comando. El comando agrupados, incluso puede ser canalizado: ps -ef | { head -1; grep "pattern" | head -5; }. ¡Útil si el patrón grep-ed tiene muchos resultados!
adicto
6

La segunda columna es la identificación del proceso; El cuarto es cuando se creó el proceso (generalmente es el momento en que comenzó su programa, pero no siempre; considere execve()y amigos); Sexto es la cantidad de tiempo de CPU consumido. Así que ha estado funcionando durante 8 días y usó casi 7 días de tiempo de CPU, lo que consideraría preocupante.

Obtener el encabezado en la misma invocación es complicado en el mejor de los casos; Solo haría una por separado ps | head -1. Puede considerar usar pslos propios métodos de selección o algo así en pgreplugar de grep, que en realidad no está diseñado para pasar encabezados.

geekosaur
fuente
¿Qué es el 83?
Webnet
Prioridad actual del proceso, que se basa en su uso anterior de CPU y E / S y el nicevalor asignado por el usuario o el sistema . Los números más pequeños son de mayor prioridad. En este caso, grepes la prioridad 0 porque se bloqueó en las lecturas de disco y cedió para escribir su salida, y PNetTNetServer.bines un gran número porque usa constantemente su segmento de tiempo sin bloquear. (La programación es compleja y los detalles dependerán del planificador exacto que se use)
Geekosaur
5

La solución egrep es simple y útil, pero, por supuesto, depende de que el encabezado siempre contenga 'PID' (sin embargo, una suposición más que razonable) y la misma cadena no ocurre en ningún otro lugar. Supongo que esto es suficiente para sus necesidades, pero en caso de que alguien quiera una alternativa, hay sed.

Sed le permite simplemente decir "imprima la primera línea, luego cualquier línea que contenga el patrón". Por ejemplo:

ps auxwww | sed -n '1p; /PROCESS_NAME_TO_SEARCH/p;'

Agregar /sed -n/d;al filtro se sedimentó:

ps auxwww | sed -n '1p; /sed -n/d; /PROCESS_NAME_TO_SEARCH/p;'
Eduardo Ivanec
fuente
/sed -n/dno es correcto. Es posible que tenga algún comando existente sed -nque desea imprimir. El truco es usar sed -n '1p; /[P]ROCESS_NAME_TO_SEARCH/p'. ;-) Nota []alrededor de cualquier carácter en la cadena de búsqueda.
anishsane
4

alternativa más fácil: ps -ef | { head -1; grep GMC; }

reemplace el número con el número de líneas en las que se muestra su encabezado.

AllBlackt
fuente
1
Me gusta este enfoque, pero el comando necesita otro punto y coma al final. ps -ef | { head -1; grep GMC; }. También me gusta en una función como la siguiente:function pgrep() { ps -ef | { head -1; grep $@; } }
Brett
1

podrías obtener el pid con pgrep

pgrep PNetTNetServer

y luego usa ps con el pid

ps u 12345

o incluso combinar los dos en un comando

ps u `pgrep PNetTNetServer`

Esto mostraría solo la línea que desea e incluiría el encabezado.

James
fuente
0

Escribí un pequeño programa Perl que imprimirá

  • la primera línea y todas las líneas coincidentes, si hay coincidencias, o
  • nada, si no hay coincidencias.

A menudo lo uso como ps | 1andre GMC, pero también puede tomar argumentos de archivo (cada archivo proporciona su propia línea de encabezado para las coincidencias realizadas en las líneas de ese archivo).

#!/usr/bin/perl

#
# 1andre <regexp> [<file> ...]
#
#   1 -           first ({1}st)
# and -                  {and}
#  re - (lines matching) {re}gexp
#
# If no <files> are given (or "-" is given as a <file>) stdin is
# used.
#
# If any lines from each <file> match the <regexp>, print the
# first line from that <file> and all the matching lines from
# that <file>.
#

use strict;
use warnings;

if(scalar @ARGV < 1) {
  printf STDERR "usage: %s <regexp> [<file> ...]\n", $0;
  exit 1;
}

my $re = shift;
my $header;

while(<>) {
  if($. == 1) {
    $header = $_;
  } elsif(m/$re/) {
    if(defined $header) {
      print $header;
      undef $header;
    }
    print;
  }
} continue {
  # close resets $. when we get to the end of each file that <> is processing
  close ARGV if eof;
}
Chris Johnsen
fuente