Skip to content

Finding Processes by Files and Ports


pgrep answers “is a process with this name running.” Plenty of real problems start from the opposite direction: you know a file or a port is the problem, and you need to find out which process is behind it. “Address already in use.” “Device is busy.” A log file you can’t delete because something’s still writing to it. This chapter covers the two tools built for exactly that — searching by what’s being used, not by process name.

Everything Is A File — Including Network Connections

This chapter leans on an idea that’s been implicit for Linux. An enormous range of things are represented as file-like objects that a process can open — regular files, directories, devices, and, less obviously, network sockets. A process with an open TCP connection is, from the kernel’s perspective, holding something conceptually similar to an open file. This is exactly why lsof — “list open files” — is also the standard tool for inspecting network connections, not just files on disk.

lsof: List Open Files

Run with no arguments, lsof lists every open file held by every process on the system — a genuinely enormous, mostly unfiltered wall of output. In practice, you’ll almost always run it against something specific.

Finding What’s Using A Specific File

lsof /var/log/syslog

This shows every process currently holding that file open — useful the moment you hit “file is busy” or “permission denied” errors that don’t make sense given the permissions you’ve already checked.

Reading The Output

COMMAND    PID  USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
rsyslogd   612  root    7w   REG  259,1    88210  131074 /var/log/syslog
ColumnMeaning
COMMANDThe process name holding this open
PIDIts process ID — feed this straight into the ps -p or kill commands
USERWho owns the process
FDFile descriptor number, and how it’s open — r (read), w (write), u (read/write)
TYPEWhat kind of thing this is — REG (regular file), DIR, IPv4/IPv6 (network socket), and others
DEVICEThe device number where the file or resource resides. For example, 259,1 identifies a particular block device
SIZE/OFFThe file size in bytes, or the file offset for certain types of open files. For some resources, it may be 0 or -
NODEThe inode number for a file, or another identifier for resources that don’t use regular filesystem inodes
NAMEThe actual file path, or for network connections, the address and port

That FD column matters more than it looks — 7w tells you not just that rsyslogd has this file open, but that it has it open for writing, which is exactly the kind of detail that explains why you can’t also write to it yourself right now.

Finding What’s Using A Port

This is one of the most common reasons to reach for lsof at all — a service fails to start with an “address already in use” error, and you need to know what’s already occupying that port.

sudo lsof -i :8080

-i filters to network connections, and :8080 narrows it to that specific port. You’ll typically need sudo here, since seeing another user’s network connections requires elevated privileges the same way seeing their processes fully often does.

COMMAND   PID  USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
python3  2044  you     3u  IPv4  38291      0t0  TCP *:8080 (LISTEN)

That LISTEN at the end tells you this process is waiting for incoming connections on that port — exactly what you’d expect from a server. Now you know both the process name and PID responsible, which is everything you need to either investigate it further or stop it.

A Few More Common Filters

lsof -u alice

Every file currently open by processes belonging to alice.

lsof -p 2044

Every file a specific, already-known PID has open — the reverse direction from searching by file, useful once ps or pgrep has already given you a PID and you want to know what it’s touching.

fuser: A Simpler, More Targeted Tool

Normal Usage

lsof is comprehensive but verbose. fuser answers a narrower question more directly: which process IDs are using this specific file or mount point, with less output to parse through.

fuser ~/demo/simplefile

Output:

/home/you/demo/simplefile: 10249 11383

This prints just the PIDs using that file — no table, no columns, just the numbers, ready to feed into another command if needed.

Verbose Output

Add -v for a more readable, verbose form closer to lsof’s output:

fuser -v /var/log/syslog

Output:

                     USER        PID ACCESS COMMAND
/home/iamalice/demo/simplefile:
                     iamalice  10249 F.... hangaround
                     iamalice  11383 F.... hangaround

Reading The ACCESS Column

That F.... isn’t decoration — each position represents a different way a process can be using the target, and more than one can apply at once:

LetterMeaning
cThe process has this as its current working directory
eThe process is executing this file as its running program
fThe process has this file open (shown alongside other letters; plain read access on its own is often just left blank)
FThe process has this file open for writing
rThe process is using this as its root directory (relevant in a chroot)
mThe process has this mapped into memory (mmap) — common for shared libraries

A dot in any position simply means that particular access type doesn’t apply. F.... in the example above means: open for writing, nothing else — exactly what you’d expect from the hangaround example process actively writing to that file. Seeing an e instead, for instance, would tell you a completely different story — that some running program’s actual executable is that file, not just a file it has open.

fuser Can Send Signals, Not Just Report

This is the part lsof can’t do at all: fuser can terminate every process using a target directly, with -k:

sudo fuser -k ~/demo/simplefile

This sends a termination signal to every PID using that file, all at once — no need to extract PIDs and pass them to kill yourself. By default this sends SIGTERM, the same graceful-termination signal you’ll get the full explanation of in the Understanding Signals file coming up shortly in this section; you can specify a different one the same way kill accepts signal names, covered properly there too:

sudo fuser -k -TERM ~/demo/simplefile
sudo fuser -k -KILL ~/demo/simplefile

Warning

-k kills every matching process immediately, with no per-process confirmation by default — genuinely risky against something like a mount point with several unrelated processes touching it. Add -i (interactive) to be prompted before each individual kill, which is worth making a habit rather than an afterthought:

sudo fuser -ki ~/demo/simplefile

This is exactly the same caution that applies to pkill and killall in the Killing Processes chapter later in this section — a command that can act on multiple matched processes at once deserves the same “verify before you act” discipline as any of them.

Filtering By Protocol: -4, -6, -n

When checking a port, fuser needs to know which network namespace and IP version you mean, since the same port number can be in use over TCP and UDP simultaneously, or over both IPv4 and IPv6:

sudo fuser -n tcp 8080/tcp
sudo fuser -4 8080/tcp
sudo fuser -6 8080/tcp

-n tcp (or -n udp) makes the namespace explicit rather than relying on the /tcp or /udp suffix alone; -4/-6 narrow results to just that IP version, useful when a port shows unexpected results because something’s bound to it over the version you weren’t expecting.

A Real Example: Can’t Unmount A Device

Recall mounting from the Storage section later in this course — occasionally you’ll try to unmount something and get a “device is busy” error, because some process still has a file open somewhere inside that mount point. fuser handles this exact case cleanly with -m (mount point):

fuser -vm /mnt/usb-drive

This shows every process with anything open anywhere under /mnt/usb-drive — even a file several directories deep — which is precisely why the unmount is failing. With the ACCESS column now understood, you can tell at a glance whether a process merely has something open for reading (f) versus actively writing (F) or has that mount point as its current directory (c) — genuinely useful context for deciding whether it’s safe to just kill it or better to let it finish first.

fuser For Ports

sudo fuser 8080/tcp

Same underlying question as lsof -i :8080, answered more tersely — just the PID, nothing else, which is often all you actually need once you already know what you’re looking for. Combine with everything above — -v for detail, -k/-i to act on it directly — once you know exactly which port and process you’re dealing with.

lsof vs. fuser: Which One To Reach For

lsoffuser
Output detailRich — user, file descriptor mode, type, full pathMinimal — mostly just PIDs
Best forInvestigating what a process is doing with a file or portQuickly answering who is using it, especially mount points
Learning curveMore columns to interpretFaster to read at a glance

In practice: reach for fuser when you already know exactly what you’re checking and just want the PID fast — a busy mount point, a specific port. Reach for lsof when you need more context — multiple processes might be involved, or you need to see how something is open, not just that it’s open.

What’s Next

You now have three complementary ways to find a process: by name or pattern (pgrep), by the file or port it’s using (lsof/fuser), and by scanning the full picture (ps). The next chapter adds a fourth angle entirely — watching processes live, as their resource usage changes in real time, with top and htop.

Last updated on