Comment grep sortie ps avec des en-têtes

26

Comment puis-je grep la sortie PS avec les en-têtes en place?

Ces deux processus constituent une application en cours d'exécution sur mon serveur ....

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

ne 6-22:01:17signifie pas qu'il est en cours depuis 6 jours? Je cherche à déterminer la durée de la durée du processus ...

La 2e colonne est-elle l'ID du processus? Donc, si je le fais, kill 32017cela tuera le 2ème processus?

Webnet
la source

Réponses:

37
ps -ef | egrep "GMC|PID"

Remplacez le "GMC" et les pscommutateurs si nécessaire.

Exemple de sortie:

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
la source
8
Ce serait bien d'ajouter quelques informations sur «pourquoi» cela fonctionne.
Elijah Lynn
2
Non, c'est un exercice pour l'utilisateur.
Hyppy
@ElijahLynn Il correspond au texte dans l'en-tête - dans ce cas, PID. Mais vous pouvez l'échanger contre UID, PTIME ou autre chose dans l'en-tête ...
Ben Creasy
5
ps -eSélectionne donc tous les processus, et ps -fest une liste au format complet qui montre les en-têtes de colonne. Ensuite, nous dirigeons les en-têtes de colonne et la sortie vers egrep, qui est grep étendu et permet au tuyau |d'avoir une signification spéciale, qui est OU (ce OU cela). Vous finissez donc par faire correspondre le PID dans les en-têtes de colonne et les lignes de sortie qui comptent.
Elijah Lynn
J'ai dû utiliser des guillemets simples dans la commande egrep / grep -E dans Ubuntu 16.04, par exemple: ps -ef | grep -E 'GMC|PID'
Vlax
13

Grâce à geekosaur, je voudrais utiliser cette commande pour vos demandes, plutôt qu'une commande séparée:

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

L'astuce consiste à utiliser le ";" pris en charge par le shell pour chaîner la commande.

Vic Lau
la source
c'est plus propre et plus robuste que la réponse acceptée. Il n'affirme pas que l'en-tête contient un PID et n'ajoute pas de complexité à la chaîne grep.
7yl4r
2
oh attendez ... vous avez ps -efrépété. encore mieux estps -ef | { head -1 ; grep "your-pattern" ; }
7yl4r
@ 7yl4r n'a jamais utilisé cette capacité d'obus. J'ai essayé votre commande améliorée, fonctionne parfaitement! J'ai appris, :)
Vic Lau
3
Explication trouvée sur cette technique, appelée 'Grouping Commands', pour la curiosité des autres, voir: gnu.org/software/bash/manual/html_node/Command-Grouping.html
Vic Lau
@ 7yl4r grande technique! Je cherchais comment ne pas répéter la commande. La commande groupée peut même être canalisé: ps -ef | { head -1; grep "pattern" | head -5; }. Utile si le motif grep-ed a beaucoup de résultats!
accro le
6

La deuxième colonne est l'ID du processus; 4ème, c'est quand le processus a été créé (c'est généralement l'heure à laquelle votre programme a commencé, mais pas toujours; réfléchissez execve()et amis); 6e est la quantité de temps CPU consommée. Il fonctionne donc depuis 8 jours et utilise près de 7 jours de temps processeur, ce que je considérerais comme inquiétant.

Obtenir l'en-tête dans la même invocation est au mieux délicat; Je ferais juste un séparé ps | head -1. Vous pourriez envisager d'utiliser psles propres méthodes de sélection ou quelque chose comme pgrepau lieu de grep, qui n'est pas vraiment conçu pour passer les en-têtes.

geekosaure
la source
C'est quoi 83?
Webnet
Priorité de processus actuelle, qui est basée sur son utilisation passée du processeur et des E / S et la nicevaleur affectée par l'utilisateur ou le système . Les petits nombres ont une priorité plus élevée. Dans ce cas, la greppriorité est 0 car elle a été bloquée lors des lectures de disque et a donné lieu à l'écriture de sa sortie, et PNetTNetServer.binest un grand nombre car elle utilise régulièrement sa tranche de temps sans blocage. (L'ordonnancement est complexe et les détails dépendront de l'ordonnanceur exact utilisé.)
geekosaur
5

La solution egrep est simple et utile, mais bien sûr, vous dépendez de l'en-tête contenant toujours «PID» (une hypothèse plus que raisonnable, cependant) et la même chaîne ne se produisant pas ailleurs. Je suppose que cela suffit pour vos besoins, mais au cas où quelqu'un voudrait une alternative, il y a sed.

Sed vous permet simplement de dire "imprimer la première ligne, puis toute ligne contenant le motif". Par exemple:

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

Ajouter /sed -n/d;au filtre se séduit:

ps auxwww | sed -n '1p; /sed -n/d; /PROCESS_NAME_TO_SEARCH/p;'
Eduardo Ivanec
la source
/sed -n/dce n'est pas correct. Certaines commandes existantes peuvent avoir sed -n, que vous vouliez imprimer. L'astuce est d'utiliser sed -n '1p; /[P]ROCESS_NAME_TO_SEARCH/p'. ;-) Notez []autour de n'importe quel caractère dans la chaîne de recherche.
anishsane
4

alternative plus simple: ps -ef | { head -1; grep GMC; }

remplacez le nombre par le nombre de lignes sur lesquelles votre en-tête est affiché.

AllBlackt
la source
1
J'aime cette approche mais la commande a besoin d'un autre point-virgule à la fin. ps -ef | { head -1; grep GMC; }. Je l'aime aussi dans une fonction comme la suivante:function pgrep() { ps -ef | { head -1; grep $@; } }
Brett
1

vous pourriez obtenir le pid avec pgrep

pgrep PNetTNetServer

puis utilisez ps avec le pid

ps u 12345

ou même combiner les deux en une seule commande

ps u `pgrep PNetTNetServer`

Cela montrerait juste la ligne que vous voulez et inclurait l'en-tête.

James
la source
0

J'ai écrit un petit programme Perl qui imprimera

  • la première ligne et toutes les lignes correspondantes, s'il y a des correspondances, ou
  • rien, s'il n'y a pas de correspondance.

Je l'utilise le plus souvent comme ps | 1andre GMC, mais il peut également prendre des arguments de fichier (chaque fichier fournit sa propre ligne d'en-tête pour les correspondances faites sur les lignes de ce fichier).

#!/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
la source