Jak grepować wyjście ps za pomocą nagłówków

26

Jak mogę grepować wyjście PS z umieszczonymi nagłówkami?

Te dwa procesy tworzą aplikację działającą na moim serwerze ....

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

nie 6-22:01:17oznacza to, że został uruchomiony przez 6 dni? Próbuję ustalić, jak długo trwa proces ...

Czy druga kolumna jest identyfikatorem procesu? Więc jeśli kill 32017to zrobię, zabije drugi proces?

Webnet
źródło

Odpowiedzi:

37
ps -ef | egrep "GMC|PID"

Wymień „GMC” i ps przełączniki w razie potrzeby.

Przykładowe dane wyjściowe:

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
źródło
8
Dobrze byłoby dodać trochę informacji o tym „dlaczego” to działa.
Elijah Lynn
2
Nie, to ćwiczenie dla użytkownika.
Hyppy
@ElijahLynn Dopasowuje tekst w nagłówku - w tym przypadku PID. Ale możesz zamienić go na UID, PTIME lub cokolwiek innego w nagłówku ...
Ben Creasy
5
ps -eWybiera więc wszystkie procesy i ps -fjest listą w pełnym formacie, która pokazuje nagłówki kolumn. Następnie potokujemy nagłówki kolumn i wyprowadzamy je do egrep, który jest rozszerzonym grep i pozwala na |specjalne znaczenie potoku , którym jest OR (to OR to). W rezultacie dopasowujesz PID w nagłówkach kolumn i linie wyjściowe, które mają znaczenie.
Elijah Lynn
Musiałem użyć prostych cudzysłowów w poleceniu egrep / grep -E w Ubuntu 16.04, np .: ps -ef | grep -E 'GMC|PID'
Vlax
13

Dzięki geekozaurowi chciałbym użyć tego polecenia do swoich potrzeb, a nie oddzielnego polecenia:

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

Trudne jest skorzystanie z „;” obsługiwany przez powłokę w celu połączenia polecenia.

Vic Lau
źródło
jest to czystsze i bardziej niezawodne niż zaakceptowana odpowiedź. Nie potwierdza, że ​​nagłówek zawiera PID i nie dodaje złożoności do łańcucha grep.
7yl4r
2
oh czekaj ... masz ps -efpowtórzenie. jeszcze lepiej jestps -ef | { head -1 ; grep "your-pattern" ; }
7yl4r
@ 7yl4r nigdy nie używał tej zdolności powłoki. Próbowałem twoje ulepszone polecenie, działa idealnie! Nauczyłem się, :)
Vic Lau,
3
Znalezione wyjaśnienie na temat tej techniki, zwanej „komendami grupowania”, dla ciekawości innych, patrz: gnu.org/software/bash/manual/html_node/Command-Grouping.html
Vic Lau
@ 7yl4r świetna technika! Szukałem, jak nie powtarzać polecenia. Zgrupowane polecenie może nawet być odprowadzone: ps -ef | { head -1; grep "pattern" | head -5; }. Przydatne, jeśli wzór grep-ed ma wiele wyników!
uzależniony
6

Druga kolumna to identyfikator procesu; Czwarty to czas, w którym proces został utworzony (zwykle jest to czas uruchomienia programu, ale nie zawsze; rozważexecve() i przyjaciele); Szósta to ilość zajętego czasu procesora. Działa więc od 8 dni i zużywa prawie 7 dni czasu procesora, co uważam za niepokojące.

Uzyskiwanie nagłówka w tym samym wywołaniu jest w najlepszym razie trudne; Po prostu zrobiłbym osobny ps | head -1. Możesz rozważyć użycie pswłasnych metod selekcji lub czegoś podobnego pgrepzamiast grep, który tak naprawdę nie jest przeznaczony do przepuszczania nagłówków.

geekozaur
źródło
Co to jest 83?
Webnet
Bieżący priorytet procesu, który jest oparty na jego przeszłym użyciu procesora i we / wy oraz nicewartości przypisanej przez użytkownika lub system . Mniejsze liczby mają wyższy priorytet. W tym przypadku grepma priorytet 0, ponieważ został zablokowany podczas odczytu dysku i dał wynik do zapisania danych wyjściowych, i PNetTNetServer.binjest dużą liczbą, ponieważ konsekwentnie wykorzystuje swój przedział czasu bez blokowania. (Planowanie jest skomplikowane, a szczegóły zależą od używanego harmonogramu.)
geekozaur
5

Rozwiązanie egrep jest proste i użyteczne, ale oczywiście zależy od nagłówka, który zawsze zawiera „PID” (choć bardziej niż rozsądne założenie) i ten sam ciąg znaków, który nie występuje nigdzie indziej. Domyślam się, że to wystarczy dla twoich potrzeb, ale w przypadku, gdy ktoś chce alternatywy, jest sed.

Sed pozwala po prostu powiedzieć „wydrukuj pierwszą linię, a następnie dowolną linię zawierającą wzór”. Na przykład:

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

Dodaj, /sed -n/d;aby odfiltrować sed:

ps auxwww | sed -n '1p; /sed -n/d; /PROCESS_NAME_TO_SEARCH/p;'
Eduardo Ivanec
źródło
/sed -n/dnie jest dobrze. Być może istnieje istniejące polecenie sed -n, które chcesz wydrukować. Sztuką jest używać sed -n '1p; /[P]ROCESS_NAME_TO_SEARCH/p'. ;-) Uwaga []wokół dowolnego znaku w ciągu wyszukiwania.
anishsane
4

łatwiejsza alternatywa: ps -ef | { head -1; grep GMC; }

zamień liczbę na liczbę wierszy, w których wyświetlany jest nagłówek.

AllBlackt
źródło
1
Podoba mi się to podejście, ale polecenie wymaga na końcu innego średnika. ps -ef | { head -1; grep GMC; }. Podoba mi się również w funkcji takiej jak:function pgrep() { ps -ef | { head -1; grep $@; } }
Brett
1

możesz dostać pid z pgrep

pgrep PNetTNetServer

a następnie użyj ps z pid

ps u 12345

lub nawet połączyć je w jedno polecenie

ps u `pgrep PNetTNetServer`

Spowoduje to wyświetlenie tylko żądanej linii i dołączenie nagłówka.

James
źródło
0

Napisałem mały program w Perlu, który wydrukuje

  • pierwsza linia i wszystkie linie pasujące, jeśli są jakieś dopasowania, lub
  • nic, jeśli nie ma żadnych dopasowań.

Najczęściej używam go w ten sposób ps | 1andre GMC, ale może również przyjmować argumenty pliku (każdy plik ma własną linię nagłówka dla dopasowań wykonanych w liniach z tego pliku).

#!/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
źródło