Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How can I grep the PS output with the headers in place?

These two process make up an app running on my server....

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

does 6-22:01:17 mean that it's been running for 6 days? I'm tring to determine the length of how long the process has been running...

Is the 2nd column the process id? So if I do kill 32017 it'll kill the 2nd process?

share|improve this question
up vote 19 down vote accepted
ps -ef | egrep "GMC|PID"

Replace the "GMC" and ps switches as needed.

Example output:

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

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
share|improve this answer
Would be good to add some info on 'why' this works. – Elijah Lynn Jan 29 at 20:21
No, that's an exercise for the user. – Hyppy Jan 29 at 20:23

Thanks to geekosaur, I would like to use this command for your demands, rather than a separated command:

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

The tricky is to make use of the ";" supported by the shell to chain the command.

share|improve this answer

Second column is the process id; 4th is when the process was created (this is usually the time your program started, but not always; consider execve() and friends); 6th is the amount of CPU time consumed. So it's been running for 8 days and used almost 7 days of CPU time, which I would consider worrisome.

Getting the header in the same invocation is tricky at best; I'd just do a separate ps | head -1. You might consider using ps's own selection methods or something like pgrep instead of grep, which isn't really designed to pass headers through.

share|improve this answer
What's the 83 ? – Webnet May 11 '11 at 20:39
Current process priority, which is based on its past CPU and I/O usage and the user- or system-assigned nice value. Smaller numbers are higher priority. In this case, grep is priority 0 because it was blocked on disk reads and yielded to write its output, and PNetTNetServer.bin is a large number because it consistently uses up its timeslice without blocking. (Scheduling is complex and the details will depend on the exact scheduler being used.) – geekosaur May 11 '11 at 20:46

The egrep solution is simple and useful, but of course you depend on the header always containing 'PID' (a more than reasonable assumption, though) and the same string not ocurring elsewhere. I'm guessing this is enough for your needs, but in case someone wants an alternative there's sed.

Sed lets you just say "print the first line, then any line containing the pattern". For example:

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

Add /sed -n/d; to filter sed itself out:

ps auxwww | sed -n '1p; /sed -n/d; /PROCESS_NAME_TO_SEARCH/p;'
share|improve this answer

you could get the pid with pgrep

pgrep PNetTNetServer

and then use ps with the pid

ps u 12345

or even combine the two into one command

ps u `pgrep PNetTNetServer`

This would show just the line you want, and include the header.

share|improve this answer

I wrote a small Perl program that will print

  • the first line and all lines matching, if there are any matches, or
  • nothing, if there are no matches.

I most often use it like ps | 1andre GMC, but it can also take file arguments (each file provides its own header line for matches made on lines from that file).


# 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;
} continue {
  # close resets $. when we get to the end of each file that <> is processing
  close ARGV if eof;
share|improve this answer

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

replace the number with the number of lines your header is displayed on.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.