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.
top
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
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
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.
pidof
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.
jobs
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
lsof
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 :)