12

I'm running a Mac and want to filter the output of the top command for a particular process such that only the PID, COMMAND and %CPU columns are displayed.

After getting the PID of the process, I run:

top -pid 1234

However this displays more than 15 columns for that process. Can I pipe the output of 'the command in to awk and display only the:

PID COMMAND %CPU

columns?

I don't want to store the output in a text file and then process it. I'm interested in monitoring the process in real time.

3 Answers 3

9
top -pid 3907 -stats "pid,command,cpu"
  • -pid 3907: your process ID
  • -stats pid,command,cpu: only show process ID, name and CPU%

No need to run awk on the output.


If you want to post-process the output, use -l 0 to run in logging mode (0 means indefinitely, everything else limits number of samples). Output will look like this (two repetitions):

Processes: 72 total, 3 running, 1 stuck, 68 sleeping, 326 threads 
2011/05/10 19:15:13
Load Avg: 0.14, 0.14, 0.09 
CPU usage: 20.0% user, 26.66% sys, 53.33% idle 
SharedLibs: 5304K resident, 5208K data, 0B linkedit.
MemRegions: 16345 total, 1048M resident, 54M private, 338M shared.
PhysMem: 726M wired, 1802M active, 687M inactive, 3215M used, 750M free.
VM: 169G vsize, 1036M framework vsize, 5261732(0) pageins, 552476(0) pageouts.
Networks: packets: 46747406/52G in, 32528901/3715M out.
Disks: 9452898/244G read, 11226269/293G written.

PID   COMMAND      %CPU
3907  WindowServer 0.0 
Processes: 72 total, 3 running, 1 stuck, 68 sleeping, 326 threads 
2011/05/10 19:15:14
Load Avg: 0.13, 0.14, 0.09 
CPU usage: 0.95% user, 1.90% sys, 97.14% idle 
SharedLibs: 5304K resident, 5208K data, 0B linkedit.
MemRegions: 16346 total, 906M resident, 54M private, 386M shared.
PhysMem: 726M wired, 1802M active, 687M inactive, 3215M used, 751M free.
VM: 169G vsize, 1036M framework vsize, 5261732(0) pageins, 552476(0) pageouts.
Networks: packets: 46747406/52G in, 32528901/3715M out.
Disks: 9452898/244G read, 11226269/293G written.

PID   COMMAND      %CPU
3907  WindowServer 2.7 

Use awk or a similar tool to only display every 13th line (as these lines contain the values in that example):

$ top -l 0 -pid 3907 -stats pid,command,cpu | awk 'NR%13==0'
3907  WindowServer 0.0 
3907  WindowServer 1.3 
3907  WindowServer 2.2 
2
  • # top -p1 -stats "pid,command,cpu" top: unknown option 't'
    – AstraSerg
    Jan 4, 2020 at 7:17
  • @AstraSerg Works for me. Note that this is a Mac OS question, which has a different top than Linux.
    – Daniel Beck
    Jan 5, 2020 at 15:35
6

This certainly can be done and I'm going to explain how I would do it. I'm not pretending this is an optimal approach, but it does the job. I am using Linux (and bash shell), so the default behavior of my top may be slightly different. Thus you may need to tune this mini-howto for your particular scenario.

  1. Just run top, without any arguments:

    $ top

    Here is the header and a relevant line from my output:

    PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND

    2569 user 20 0 339m 86m 10m S 7.8 6.9 6:42.99 java

    I have picked up a process that stays in memory for some time and actually consumes CPU, I will be using it as test process for reaching the final goal.

  2. By default, top runs in interactive mode. This doesn't suit me, I want to capture the relevant data and print it. I will handle the task of displaying the data interactively after that. Relevant quotes from top manpage:

    -b : Batch mode operation Starts top in 'Batch mode', which could be useful for sending output from top to other programs or to a file. In this mode, top will not accept input and runs until the iterations limit you've set with the '-n' command-line option or until killed.

    -n : Number of iterations limit as: -n number Specifies the maximum number of iterations, or frames, top should produce before ending.

    This is the adjusted top command that prints output only once, then exits:

    $ top -b -n 1

  3. I know the PID I want to watch, so I'll add one more restriction to top, so it prints data only about that process:

    $ top -b -n 1 -p 2569

  4. Even in batch mode, top still prints a header, containing misc system-wide stats like uptime, free memory/swap etc. I don't need this. All I need is only one line - the one that contains data about my process, so I'll cut it from the whole output like this:

    $ top -b -n 1 -p 2569 | tail -n 2 | head -n 1

    As you can see, I've got the second line from 1.

  5. I'll pipe this line to awk to extract only the columns I need:

    $ top -b -n 1 -p 2569 | tail -n 2 | head -n 1 | awk '{print $1, $12, $9}'

  6. Until now, I've been doing these manipulations in command line, now it's the moment to add some persistence and flexibility to our hardcoded particular case. I am moving the whole line into a simple shell script. I'll call it 3top, the name is emphasized because it will be used later:

    #!/bin/bash

    top -b -n 1 -p 2569 | tail -n 2 | head -n 1 | awk '{print $1, $12, $9}'

  7. The PID number is hardcoded, here's how to make the script to accept it as command line argument:

    #!/bin/bash

    top -b -n 1 -p "$1" | tail -n 2 | head -n 1 | awk '{print $1, $12, $9}'

    To make 3top display stats about PID 2569, it must be called like this:

    $ ./3top 2569

  8. I also want percentage displayed after CPU load, so I'm tuning my 3top script like this:

    #!/bin/bash

    out=$(top -b -n 1 -p "$1" | tail -n 2 | head -n 1 | awk '{print $1, $12, $9}')

    echo "$out%"

    I have redirected the whole output of a chain of commands (connected through pipes) into a variable. Then I just print it using echo and add a '%' at the end, since CPU load is the last field

  9. At this point I have a batch script that accepts a PID as argument and prints stats once. Want real time monitoring instead? It's easy, because watch can do it! Run the script like this:

    $ watch -n 1 3top 2569

    It will do real time monitoring by running 3top once per second.

2
  • 12
    The user is on OS X and has no Gnu top. invalid option or syntax: -b. No idea why this was repeatedly upvoted.
    – Daniel Beck
    May 10, 2011 at 17:20
  • 5
    Gnu top (in procps) cannot be installed using Homebrew, MacPorts or Fink and cannot be compiled from source using either make or cc top.c.
    – Daniel Beck
    May 10, 2011 at 18:11
2

The top display format is customizable, but there is not a way to specify display options at the command line. If you are inventive, however, you can probably do what you need by cleverly manipulating the ~/.toprc file.

Assuming you have not already customized the display of top (and do not have a ~/.toprc file):

  1. Launch top.
  2. Press f to enter field select mode.
  3. For each field that has an * next to it that you do not want, press the corresponding letter to deselect that field. For example, press e to deselect the User Name field. When you are done, you should only have an * next to Process Id, CPU usage, and Command name/line.
  4. Press Space to return to the main window.
  5. Press W (i.e. Shift+w) to save the current layout to your ~/.toprc file.
  6. Quit top, then relaunch to verify that your settings are saved.
  7. When you want to return to the default layout, rename ~/.toprc to something like ~/min.toprc before launching top. When you want to switch to the minimal layout, rename ~/min.toprc back to ~/.toprc before launching top.

This file renaming and launching top can probably be worked into a simple shell script by someone with an ounce more experience and knowledge than me. You will need special consideration if your regular top layout has already been customized.

1
  • Is it possible to add a filter (even if manually) to .toprc? I like to add the filter RUID>999 at startup.
    – DrBeco
    Apr 12, 2017 at 5:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .