Como grep saída ps com cabeçalhos

26

Como posso receber a saída PS com os cabeçalhos no lugar?

Esses dois processos compõem um aplicativo em execução no meu 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

não 6-22:01:17significa que ele foi executado por 6 dias? Estou tentando determinar a duração de quanto tempo o processo está em execução ...

A 2ª coluna é o ID do processo? Então, se eu fizer kill 32017isso, matará o segundo processo?

Webnet
fonte

Respostas:

37
ps -ef | egrep "GMC|PID"

Substitua o "GMC" e os pscomutadores, conforme necessário.

Exemplo de saída:

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
Hyppy
fonte
8
Seria bom adicionar algumas informações sobre 'por que' isso funciona.
Elias Lynn
2
Não, isso é um exercício para o usuário.
Hyppy
@ElijahLynn Corresponde ao texto no cabeçalho - neste caso, PID. Mas você pode trocá-lo para o UID, ÓPTIMO, ou qualquer outra coisa no cabeçalho ...
Ben Creasy
5
Então, ps -eseleciona todos os processos e ps -fé uma listagem em formato completo que mostra os cabeçalhos das colunas. Em seguida, canalizamos os cabeçalhos das colunas e saímos para egrep, que é estendido para grep, e permite que o canal |tenha um significado especial, que é OR (esse OR que). Então você acaba combinando o PID nos cabeçalhos das colunas mais as linhas de saída que importam.
Elias Lynn
Eu tive que usar aspas simples no comando egrep / grep -E no Ubuntu 16.04, por exemplo: ps -ef | grep -E 'GMC|PID'
Vlax 3/17
13

Graças ao geekosaur, eu gostaria de usar este comando para suas demandas, em vez de um comando separado:

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

O mais complicado é fazer uso do ";" suportado pelo shell para encadear o comando.

Vic Lau
fonte
isso é mais limpo e mais robusto que a resposta aceita. Ele não afirma que o cabeçalho possui PID e não adiciona complexidade à cadeia grep.
7yl4r
2
oh espera ... você ps -efrepetiu. o melhor mesmo éps -ef | { head -1 ; grep "your-pattern" ; }
7yl4r
@ 7yl4r nunca usou essa capacidade de shell. Eu tentei o seu comando melhorado, funciona perfeitamente! Got aprendeu, :)
Vic Lau
3
Encontrei uma explicação sobre essa técnica, chamada 'Comandos de agrupamento', para curiosidade de outras pessoas, consulte: gnu.org/software/bash/manual/html_node/Command-Grouping.html
Vic Lau
@ 7yl4r ótima técnica! Eu estava procurando como não repetir o comando. O comando agrupados pode até mesmo ser canalizado: ps -ef | { head -1; grep "pattern" | head -5; }. Útil se o padrão grep-ed tiver muitos resultados!
addicted
6

Segunda coluna é a identificação do processo; A quarta é quando o processo foi criado (geralmente é o momento em que o programa foi iniciado, mas nem sempre; consideram execve()e amigos); 6 é a quantidade de tempo de CPU consumida. Portanto, ele está em execução há 8 dias e usou quase 7 dias de tempo de CPU, o que eu consideraria preocupante.

Obter o cabeçalho na mesma invocação é complicado, na melhor das hipóteses; Eu apenas faria um separado ps | head -1. Você pode considerar o uso de psmétodos de seleção próprios ou algo como, em pgrepvez de grep, que não é realmente projetado para passar os cabeçalhos.

geekosaur
fonte
Qual é o 83?
Webnet
Prioridade do processo atual, que se baseia no uso anterior de CPU e E / S e no nicevalor designado pelo usuário ou pelo sistema . Números menores são de maior prioridade. Nesse caso, grepé a prioridade 0, porque foi bloqueado nas leituras do disco e produziu para gravar sua saída, e PNetTNetServer.biné um número grande, porque consome constantemente o tempo de uso sem bloquear. (Agendamento é complexo e os detalhes dependerá do programador exata que está sendo usado.)
geekosaur
5

A solução egrep é simples e útil, mas é claro que você depende do cabeçalho que sempre contém 'PID' (uma suposição mais do que razoável) e a mesma string que não ocorre em nenhum outro lugar. Eu acho que isso é suficiente para as suas necessidades, mas no caso de alguém querer uma alternativa, existe uma solução.

Sed permite que você diga "imprima a primeira linha, depois qualquer linha que contenha o padrão". Por exemplo:

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

Adicionar /sed -n/d;ao filtro:

ps auxwww | sed -n '1p; /sed -n/d; /PROCESS_NAME_TO_SEARCH/p;'
Eduardo Ivanec
fonte
/sed -n/dnão está certo. Pode ter algum comando existente sed -nque você deseja imprimir. Truque é usar sed -n '1p; /[P]ROCESS_NAME_TO_SEARCH/p'. ;-) Observe em []torno de qualquer caractere na string de pesquisa.
Anishsane 12/07/2018
4

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

substitua o número pelo número de linhas em que seu cabeçalho é exibido.

AllBlackt
fonte
1
Eu gosto dessa abordagem, mas o comando precisa de outro ponto e vírgula no final. ps -ef | { head -1; grep GMC; }. Também gosto em uma função como a seguinte: #function pgrep() { ps -ef | { head -1; grep $@; } }
315 Brett
1

você pode pegar o pid com pgrep

pgrep PNetTNetServer

e depois use ps com o pid

ps u 12345

ou até combinar os dois em um comando

ps u `pgrep PNetTNetServer`

Isso mostraria apenas a linha desejada e incluiria o cabeçalho.

James
fonte
0

Eu escrevi um pequeno programa Perl que imprimirá

  • a primeira linha e todas as linhas correspondentes, se houver alguma correspondência, ou
  • nada, se não houver correspondências.

Costumo usá-lo com frequência ps | 1andre GMC, mas também pode receber argumentos de arquivo (cada arquivo fornece sua própria linha de cabeçalho para correspondências feitas nas linhas desse arquivo).

#!/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
fonte