Using ps -elf and Filtering its Output Effectively

To find out if a process is running and info about it in Ubuntu Linux, like what User ID it is running under and the process ID (PID), you can issue this simple command in a terminal (should work in many other Linux distros and I used it on various Unix systems for years - only tested for this article on Ubuntu 18.04):

ps -elf

The -elf options produce the most complete information for each process as best I can tell in my research without having to resort to a heck of a lot more typing.

However, this will print out every process running in the system, and you will have to wade through all that output. A better way is to filter the output, e.g., by the name of the executable invoked to run the process, or by user ID to narrow down the search:

ps -elf | head -n 1; ps -elf | grep -i search_term | grep -v grep | grep -v "ps -elf"

Just substitute the text search_term with text that will find the process you are interested in, like (part of) the executable file name. This seems like a lot to remember and type every time, but we will automate the commands below.

Example Usage

Below, I use the search term term to demonstrate because it will work since I am working on the command line in a terminal. That is, there will be a running process whose name has the letters term for grep to find.

Instructions and Output

Open a terminal window in Ubuntu Linux. Keyboard shortcut: ctrl-alt-t

Type the following on the command line then hit enter:

ps -elf | head -n 1; ps -elf | grep -i term | grep -v grep | grep -v "ps -elf"

The text in the terminal window should look similar to this now:

user@xitalogy:$ ps -elf | head -n 1; ps -elf | grep -i term | grep -v grep | grep -v "ps -elf"
F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
0 S user     14919  1394  0  80   0 - 217553 poll_s 04:14 ?       00:00:12 /usr/lib/gnome-terminal/gnome-terminal-server
user@xitalogy:$

Explanation and Discussion

There are two commands on the above command line separated by the ;. When typed in this way, the first command will execute, then the next one will immediately execute after the first. This way, the output from the two consecutive commands is not separated by a separate command line in which the user must type the second command. In this way, the column headers are immediately followed by the process info for easy reading.

First Command

The first command uses ps (the command that “reports a snapshot of current processes”) along with head (the command that “outputs the first part of a file”) to print out the first line of ps -elf in order to have the column headers just above the line or lines with the process info we are seeking. This makes reading the process info much easier:

ps -elf | head -n 1

ps -elf outputs info for every running process (-e), in long format (-l - shows extra columns of useful information), and full format (-f), which shows more info as well, including command line arguments. Hence, combined, -elf.

The pipe character, |, pipes the output of ps to head, which outputs the first few lines of a file (or in this case, stdin for head, which receives the output of ps to stdout via the pipe). The option -n controls the number of lines head displays: in this case, one. The result is to output the column header line to the console:

F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD

Second Command

The second command uses ps and grep, along with three | pipes:

ps -elf | grep -i term | grep -v grep | grep -v "ps -elf"

It pipes the output from ps -elf (discussed above) to grep -i term. This in turn pipes its output to grep -v grep and finally grep -v "ps -elf".

The -i in the first grep ignores case to make life easier. The search term is term, which will hit positive on the terminal process info ps -elf outputs for the terminal I am using because the command line used to start the terminal I am using has the word “terminal” in it, and ps -elf outputs that command line info along with the rest of the info for that process.

The second grep takes the option -v, which reverses the sense of grep, thereby only finding lines of text that do not have the search term in them, in this case grep. This is necessary to filter out the grep process itself that is invoked when these commands are run.

That is, grep will be running with a command line that includes the term term, so if not for this middle filter, there would be an extraneous second line that shows the process information for the grep commands themselves we are running when ps enumerates running processes. The same goes for the last grep which filters out the ps -elf process. Even though the ps -elf process line does not have term on it, other search terms besides term could include it, so it is there for completeness. The output from the second command looks like so:

0 S user     13982  1394  0  80   0 - 201932 poll_s 21:00 ?       00:00:07 /usr/lib/gnome-terminal/gnome-terminal-server

Both Commands Run Back to Back

Now, when these two commands are run back to back without need to pause for user input between, along with the command prompt and typed in command, we get the following desired output:

F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
0 S user     13982  1394  0  80   0 - 201932 poll_s 21:00 ?       00:00:07 /usr/lib/gnome-terminal/gnome-terminal-server

Output without Columns or Extra Filters

The following is easy to type and remember, but the output is less than optimal:

$ ps -elf | grep -i term

This is what you end up with:

0 S user     13982  1394  0  80   0 - 202082 poll_s Feb22 ?       00:00:18 /usr/lib/gnome-terminal/gnome-terminal-server
0 S user     14638 14108  0  80   0 -  5383 pipe_w 03:00 pts/1    00:00:00 grep --color=auto -i term

No helpful column headings, and an extraneous line that results from ps picking up the grep command being run by you.

Process Running or Not?

If the process you are checking out is running, it will return a second line as above if you used a successful search term. If the process is not running at the time of the issuing of the commands, you will just get the first header column with no second line:

user@xitalogy:$ ps -elf | head -n 1; ps -elf | grep -i terminabeley | grep -v grep | grep -v "ps -elf"
F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
user@xitalogy:$

That is how you can tell if the process in question is running or not - no second line. Make sure you use a good search term that will not give false positives or false negatives. Depending on the search term and the info for the various running processes, you may get more than one line of process info. You will need to inspect these lines to determine if the one you are expecting is one of them. Note the “garbage” search term for the first grep above: grep found no match for it in the output of ps -elf.

Meaning of the Output

Here is the sample output again:

F S UID        PID  PPID  C PRI  NI ADDR SZ WCHAN  STIME TTY          TIME CMD
0 S user     13982  1394  0  80   0 - 201932 poll_s 21:00 ?       00:00:07 /usr/lib/gnome-terminal/gnome-terminal-server
  • F is process Flags
  • S is minimal state display
  • UID is the User ID
  • PID is the Process ID
  • PPID is the Parent Process ID
  • C is processor utilization
  • PRI is the priority of the process
  • NI is the “nice value. This ranges from 19 (nicest) to -20 (not nice to others), see nice(1). (alias nice).”
  • ADDR is the “memory address of the process”
  • SZ is the “size in physical pages of the core image of the process.”
  • WCHAN is the ‘name of the kernel function in which the process is sleeping, a “-“ if the process is running, or a “*” if the process is multi-threaded and ps is not displaying threads.’
  • STIME is the time the command started
  • TTY is the “device number of the controlling TTY”
  • TIME is the “cumulated CPU time”
  • CMD is the command line used to start the process, along with command line arguments

Documentation - man pages

For the manual on head, type man head on the command line, or go to the Ubuntu head man page.

For the manual on ps, type man ps or go to the Ubuntu ps man page.

For the manual on grep, type man grep or go to the Ubuntu grep man page.

Automating the Commands

Typing the whole command line above every time you need it will quickly become tiresome, if you can even remember it. Below is the way to automate it:

Make a .bash_aliases File

Change to the root of your home directory (for example, cd /home/myuserid). If you do not already have a .bash_aliases file there, type the following:

touch .bash_aliases

Add a Function that Takes a Parameter

Next, add a function to do the commands to the end of your .bash_aliases file:

echo 'pself() { ps -elf | head -n 1; ps -elf | grep -i "$1" | grep -v grep | grep -v "ps -elf"; }' >> .bash_aliases

Try out the Function

This creates a function called pself that takes one parameter (the search term). Open a new terminal window, and .bash_aliases will automatically run by default on an Ubuntu Linux 18.04 machine, and you can now invoke the entire function as below:

pself my_search_term

Plug in the appropriate search term for your situation instead of my_search_term.

Using the automated function, it becomes very easy to powerfully filter the output of ps. You could use a user ID for the search term, such as root or your personal user ID. You could use a known process ID (PID) or parent process ID (PPID) to see if the process is still running, or if its parent is. Or, you could search for all processes that are started from a given generalized path, like /usr/bin or that have started from your home directory (/home/myuserid). You can also use tty to only show processes that have a controlling terminal.

Conclusion

I hope you find these techniques useful for managing processes on Ubuntu Linux and other Linux distros or Unix machines that are compatible with it.

Thanks to Pexels for the free image