Computers didn’t always multi-task. Back then it was easy to identify an out of control process (hint: it was the only one running). These days, the moment you boot up your computer, you’re immediately running hundreds of processes. Every so often your fan will kick up to 11 and just like days of yore, there’s probably only a single rogue process to blame. Other times you go to up a development server only to find that something else is already using the same port, but you have no idea which process.

Ready to go sleuthing? Let’s talk about tracking down processes, all from the command-line!

Getting Started

This article assumes you’re on a Unix-like operating system and the tools discussed are already available to you. Sometimes we’ll need to use super user privileges, which hopefully you have as well.

None of the commands in this guide are destructive in nature. All we’re going to do is figure out the process ID of running processes. The process ID can be used for destructive purposes, like killing the job, but that’s for another article.


Arguably the easiest way to find out the ID of a process is by running top.

While not as elegant as some of the examples we’re going to go over, it’s often times more than enough to get you what you need:

$ top

Which will greet you a text-based process list similar to your favorite process explorer or activity monitor.

If this is your first time seeing top, it’s probably a lot to take in.

There’s information about users, up-time, system load, available CPU and memory and then below it all, a nice list of processes.

It should look similar to this:

top - 18:51:41 up 10 days, 21:37,  3 users,  load average: 0.44, 0.41, 0.66
Tasks: 252 total,   1 running, 251 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.3 us,  0.6 sy,  0.0 ni, 97.9 id,  0.0 wa,  0.0 hi,  0.1 si,  0.0 st
MiB Mem :  32046.7 total,  15190.6 free,   3999.7 used,  12856.4 buff/cache
MiB Swap:  30517.6 total,  30162.4 free,    355.2 used.  26809.4 avail Mem

 8383 josh      20   0  809168  92024  72892 S   1.7   0.3   6:23.94 spotify
  767 root      20   0 1924628  20336   3468 S   0.7   0.1  24:17.07 containerd
 1217 josh      20   0  249872  36296  16636 S   0.7   0.1 277:54.68 Xorg
 1262 josh      20   0 3550872 311932 109312 S   0.7   1.0 321:50.42 gnome-shell
11371 josh      20   0  492308  53716  37984 S   0.7   0.2   0:45.78 gnome-terminal-
  756 root      20   0 1890252  45104  10644 S   0.3   0.1  27:54.94 dockerd
14727 josh      20   0   13576   4064   3204 R   0.3   0.0   0:00.03 top
32562 josh      20   0 1349028 362364 181136 S   0.3   1.1   2:17.46 brave
    1 root      20   0  198492   7424   5412 S   0.0   0.0   8:58.26 systemd

The list of processes is probably jumping around quite a bit, due to how you have things sorted. The default behavior is to sort the processes by the amount of CPU being used. Because of this, a processes eating up all of your CPU will be right there at the top.

If you look to the left of the process list, you’ll see a column labeled PID. That columns is where you will find the process ID. In example above, process 8383 belongs to the spotify command. If my Spotify app was getting unruly, I could take care of business knowing that ID.

It’s worth noting that a lot of applications are multi-threaded and have multiple processes running at once. Web browsers are pretty notorious for this.

Just because an processes’ ID doesn’t mean you have the main thread’s ID. If you were to kill the process ID for Chrome and it’s not the main thread’s ID, you’d probably end up killing a single tab, or extension and not the whole thing.


Let’s say that I already had a suspicion that my Spotify app was being unruly. By knowing the name of the command, in this case spotify, I could use the pidof command to get the process ID:

$ pidof spotify

By default, pidof will list all of the processes that match the name. As mentioned earlier, a process may have multiple threads, so you may have to root around a bit to determine if you have the main thread or not.

Remember that Unix-like systems may recycle process IDs, so the PID order is not a good indicator for deducing which ID may belong to the main thread.


Thus far, we’ve been finding jobs in the global scope of our system. Sometimes you have a process running in the background of your current session that you need to track down.

To help simulate some tasks in our session, let’s run the following:

$ sleep 300 &
$ sleep 600 &
$ sleep 900 &

This will run the sleep command for 5, 10 and 15 minutes and throw each process into the background of our current session.

You probably noticed each of those commands returned a number that looks very similar to the process IDs we’ve been working with. As it turns out, when you background a process, you are given the process ID so you can return to it later.

For the sake of example, let’s say we didn’t know those process IDs and wanted to see the processes in our current session:

$ jobs

Which returns the currently running jobs in the session, the order of which they were run and their status. But wait, no process ID?!

To get the process ID to show up as well, you need to include the -p argument:

$ jobs -p

Giving us results that probably look similar to this:

[1]    15765 running    sleep 300
[2]  - 15773 running    sleep 600
[3]  + 15782 running    sleep 900


Everything discussed thus far has helped us to identify rogue processes and processes that were backgrounded in our current session. One of the most frustrating things is trying to run a process or bring up a service only to find out that another process is already occupying the port.

Sure, you could just reboot your machine, but what’s the fun in that?

To easily track down which process is listening on a specific port, you can use the lsof command. By default, without any arguments, lsof is going to list all open files that belong to every open process.

Run lsof without any arguments just once to fully realize how much stuff is actually happening behind the scenes on your machine. When I ran lsof with time on my laptop, it took nearly 10 seconds to dump out everything. WOW.

Fortunately, we can pass in a few additional arguments and cut through the clutter to figure out which process is listening on a port:

$ sudo lsof -itcp:4000

The aforementioned lsof will return the process that is current listening on port 4000. The sudo is because we may not know which user account on the system may be holding the port.

Similar to top, the process ID is listed under the PID column.

Try it out, replace the port number with one that you know you have a process listening on.

What about   ps?

If you’re a command-line junky like myself, you are probably wondering why ps didn’t make the list.

Between you and me, I think ps is absolutely amazing. So much so, that I think it deserves an in depth article all it’s own :)