Linux lsof Command Cheat Sheet: Find Suspicious Processes, Open Ports, and Deleted Files
Last verified: October 26, 2026 (syntax checked against current lsof documentation behavior).
It was 2:14 a.m. when the alert fired: root volume at 100% on a production log server. The on-call engineer ran du on every directory he could think of and the numbers added up to barely 40% of the disk. Nothing was missing, nothing was growing, and yet the filesystem insisted it was full.
The culprit turned out to be a rotated log file that had been deleted while a running service still held it open. The space was never released. One command found it in about three seconds: lsof +L1.
That is the real value of lsof. It answers the question "what is this process actually touching right now?", and in Linux incident response that question comes up constantly, whether you are chasing a disk-space ghost, an unexpected listener on a high port, or a process that has no business reading your SSH config. This guide walks through the lsof commands that matter most for SOC analysts and sysadmins, grouped by the investigation they support.
Table of Contents
- What lsof Actually Shows You
- The One Gotcha: OR vs. AND Filtering
- Process, User, and File Lookups
- Network Connections and Ports: Linux Threat Hunting Basics
- File Descriptors and File Types
- Deleted Files and Disk Space Investigation
- Real-World Scenario: The Unknown Listener
- Output, Reporting, and Monitoring
- Detection and Hardening Notes
- Expert Tips
- FAQ
- Conclusion
What lsof Actually Shows You
lsof stands for "list open files." On Linux, nearly everything is a file: regular files, directories, network sockets, pipes, devices. So lsof doubles as a process-to-resource mapping tool. One caveat: it shows what a process has open right now. It is not a history of everything a process has ever accessed, so a file that was opened and closed a second ago will not appear.
A typical line of output has these columns: COMMAND, PID, USER, FD, TYPE, DEVICE, SIZE/OFF, NODE, and NAME. The two columns worth learning first are FD and TYPE.
| Column / Value | Meaning |
|---|---|
FD: cwd | The process's current working directory |
FD: txt | The executable itself |
FD: mem | Memory-mapped file, such as a shared library |
FD: 4u, 5r, 6w | Descriptor number plus mode: read, write, or read/write |
TYPE: REG / DIR | Regular file / directory |
TYPE: IPv4 / IPv6 | Internet socket |
TYPE: unix / FIFO | Unix domain socket / named pipe |
The One Gotcha: OR vs. AND Filtering
This trips up even experienced admins. By default, lsof treats multiple selection options as alternatives (logical OR). Run lsof -u alice -i and you get everything alice has open plus every Internet socket on the system, not just alice's sockets. Add -a to require all conditions to match (logical AND).
sudo lsof -a -u alice -i
What it does: lists only Internet sockets owned by user alice. When to use it: any time you combine filters, such as user plus network, PID plus port, or PID plus file descriptor. Expected output: a short list of alice's TCP/UDP sockets rather than a screen-flooding dump.
Process, User, and File Lookups
Start here when you have a suspect: a PID from top, a username from an auth log, or a file you care about.
Investigating by process
lsof -p 1234
lsof -p 1234,5678
sudo lsof -R -p 1234
sudo lsof -g 5678
lsof -p $$
These show everything one PID (or several) has open. -R adds the parent PID column where supported, which helps when you are tracing a child process back to the thing that spawned it. -g selects by process group ID, and $$ expands to your current shell's PID, which makes it a handy way to see what lsof output looks like on a process you control. Expect a table with the executable, libraries, working directory, and any open files or sockets.
Investigating by user or command name
lsof -u alice
lsof -u 1001
lsof -u ^alice
lsof -c nginx
sudo lsof -c python
sudo lsof -c java
Use -u with a username or numeric UID to see what an account is touching. The caret (^) inverts the selection, so -u ^alice shows everyone except alice, which is useful for filtering out your own noise. -c matches processes whose command name begins with the string, so -c python also catches python3. Keep in mind that a process can rename itself, so treat command names as a lead, not proof.
Who is using this file or directory?
sudo lsof /var/log/syslog
sudo lsof /etc/ssh/sshd_config
sudo lsof +d /var/log
sudo lsof +D /var/www
sudo lsof +D /media
sudo lsof /dev/sda
sudo lsof +f -- /mnt/data
Passing a path directly returns every process holding that file open. This is the command to run before log rotation, before unmounting a drive (the classic "target is busy" error), or when checking whether anything unexpected has your SSH config open. The difference between the two directory flags matters: +d looks only at files directly inside the directory, while +D walks the whole tree. On a large web root or a busy log directory, +D can take a long time and generate real I/O, so avoid it on a production host during peak load. The +f -- form tells lsof to interpret the path as a filesystem, so you get every open file on that mount.
Network Connections and Ports: Linux Threat Hunting Basics
For Linux threat hunting on a single host, network-focused lsof is often faster than reaching for a full packet capture. Always add -nP: it stops lsof from resolving hostnames and port names, which makes output faster and prevents you from misreading a port because it was translated into a service name.
Inventory listeners and connections
sudo lsof -nP -i
sudo lsof -nP -iTCP -sTCP:LISTEN
sudo lsof -nP -iTCP -sTCP:ESTABLISHED
sudo lsof -nP -iUDP
sudo lsof -i4
sudo lsof -i6
sudo lsof -U
What they do: list all Internet sockets, only listening TCP sockets, only established TCP sessions, UDP sockets, IPv4-only, IPv6-only, and Unix domain sockets respectively. When to use them: the LISTEN query is your baseline "what is this server exposing?" check. The ESTABLISHED query shows live conversations. Expected output: rows like sshd 812 root 3u IPv4 ... TCP *:22 (LISTEN). Run these as root for full visibility, because as a normal user you will only see your own processes.
Pinpoint a port, host, or range
sudo lsof -nP -iTCP:80
sudo lsof -nP -iTCP:443
sudo lsof -nP -i :8080
sudo lsof -nP -iUDP:53
sudo lsof -nP -iTCP:8000-8100
sudo lsof -nP -i @192.0.2.10
sudo lsof -nP -iTCP@192.0.2.10:443
sudo lsof -t -i :8080
sudo lsof -a -p 1234 -i
sudo lsof -a -p 1234 -iTCP:443
These answer "which process owns this port?" and "which process is talking to that address?" The -t variant prints only PIDs, which is ideal for scripting but returns multiple PIDs when several processes match. The addresses above use the documentation range 192.0.2.x, so substitute a real address. When an endpoint detection and response (EDR) alert gives you only an IP and port, this is how you map it back to a local process in seconds.
File Descriptors and File Types
lsof -a -p 1234 -d 0-2
lsof -a -p 1234 -d 5
lsof -a -p 1234 -d 3,4,5
lsof -p 1234 | grep REG
lsof -p 1234 | grep DIR
lsof -p 1234 | grep mem
lsof -p 1234 | grep PIPE
The -d flag filters by descriptor. Descriptors 0, 1, and 2 are standard input, output, and error. That matters in investigations: if a long-running daemon has stdin or stdout pointing at a network socket instead of /dev/null, that is worth a closer look, because it is a pattern associated with remote shells (a hypothesis to verify, not a verdict). The grep variants simply slice the normal output by TYPE, so you can separate libraries (mem) from data files (REG) and inter-process plumbing (PIPE). A process loading a library from /tmp or another world-writable path is the sort of finding that deserves follow-up.
Deleted Files and Disk Space Investigation
Back to the 2 a.m. page. When a file is deleted while a process still has it open, Linux keeps the data on disk until the last descriptor closes. The file vanishes from ls and du, but df still counts the space.
sudo lsof +L1
sudo lsof +L1 | grep -i log
sudo lsof -a -p 1234 +L1
sudo lsof -a -u alice +L1
What it does: +L1 selects open files with a link count below one, which in practice means deleted-but-still-open files. When to use it: whenever df and du disagree. Expected output: rows with a NLINK of 0 and a NAME ending in (deleted), along with the PID holding the space. The log-focused grep usually surfaces the culprit immediately, and the -a variants narrow it to one process or user.
Before rotating logs or unmounting storage, check who has the target open:
sudo lsof /var/log/syslog
sudo lsof +f -- /var
The usual fix for the disk-space case is to restart or reload the owning service so it releases the descriptor. Do that during an approved maintenance window, because restarting a production service has its own consequences.
Forensic note: a deleted file that a process still holds can often be read through /proc/<PID>/fd/<N>. If that file might be evidence, such as a deleted binary or a wiped log, copy it somewhere safe first and document what you did. Do not truncate it to reclaim space until you are sure you will not need it. Truncation is destructive and unrecoverable.
Real-World Scenario: The Unknown Listener
Here is a composite scenario, typical of what SOC teams encounter. A vulnerability scan flags an unexpected listener on TCP port 4444 of a Linux web server. Nobody on the team recognizes it.
- Identify the owner. Run
sudo lsof -nP -iTCP:4444. The output shows a process namedphp-fpmlistening on all interfaces, which is odd because the real php-fpm only talks over a Unix socket on this host. - Inspect the process. Run
sudo lsof -R -p <PID>to see its parent and its open files. If thetxtentry points to a path in/tmpor shows(deleted), the executable was removed after launch, a common technique to hinder analysis. - Check descriptors 0-2.
sudo lsof -a -p <PID> -d 0-2reveals whether standard streams are tied to a socket. - Look at connections.
sudo lsof -a -p <PID> -ishows any outbound sessions. - Preserve before you kill. Capture the lsof output to a file, record the PID, user, and start time, and copy the binary via
/proc/<PID>/exeif policy allows. Only then isolate the host according to your incident response plan.
Notice what lsof gave you: the owner, the parent, the executable's state, and the network exposure, all without installing anything. It will not tell you how the process got there. Pair it with auth logs, web server logs, and file integrity data to reconstruct the entry point. Treat the analysis above as a hypothesis until those sources confirm it.
Output, Reporting, and Monitoring
sudo lsof -r 5 -i
sudo lsof -r -i
sudo lsof > lsof-report.txt
sudo lsof -nP -i > network-sockets.txt
sudo lsof -p 1234 >> process-files.txt
sudo lsof | wc -l
sudo lsof | grep -F 'config.json'
sudo lsof -Fpcfn -p 1234
Repeat mode: -r 5 re-runs the listing every 5 seconds, and -r alone uses the default interval (15 seconds); both continue until you press Ctrl+C. It is a lightweight way to watch a connection appear and disappear during triage.
Reports: the redirect examples save a point-in-time snapshot. Timestamp your files, since a snapshot without a time is hard to use later. >> appends instead of overwriting.
Counting and searching: wc -l gives a rough total of lines. On modern systems, thread entries and the header row inflate that number, so treat it as a trend indicator, not an exact count of open files. grep -F does a fixed-string search, which avoids regex surprises with dots and special characters in filenames.
Machine-readable output: -F with field letters (here p PID, c command, f descriptor, n name) prints one field per line, each prefixed with its code. That is much safer to parse in scripts than splitting on whitespace, but you must interpret the field codes correctly, so check the manual for your build.
Help and version:
man lsof
lsof -h
lsof -v
The manual is long but excellent. -h prints a short usage summary, and -v prints version and build details, where supported. Different distributions ship slightly different builds, so check these before assuming a flag exists.
Detection and Hardening Notes
- Baseline your listeners. Save the output of
sudo lsof -nP -iTCP -sTCP:LISTENon known-good servers. Comparing against it later turns "is this normal?" into a diff. - Watch for deleted executables. A running process whose binary shows as
(deleted)is not automatically malicious (package updates can cause it), but it deserves a look, especially on hosts that were not just patched. - Review unexpected descriptors. Interpreters such as Python or Java holding sockets or files outside their application directory may be legitimate, or may not. Check against the application's documented behavior.
- Restrict who can see everything. Full visibility requires root, so limit sudo access and log its use. Audit tooling such as auditd can record who ran what.
- Know the blind spots. Containers, namespaces, hidepid mount options, and kernel settings change which processes and sockets lsof can see. A host-level lsof may not show the inside of a container, and a sophisticated rootkit can interfere with any user-space tool. No single command gives you guaranteed visibility.
For teams evaluating endpoint detection and response tools, lsof is a good reminder of what good telemetry looks like: process, parent, file, and socket in one view. EDR platforms collect this continuously, while lsof gives you the same kind of snapshot by hand when the agent is missing or you need a quick second opinion.
Expert Tips
- Always use
-nPon network queries. It is faster, avoids DNS lookups that leak your investigation, and removes naming ambiguity. - Run as root, but know why. Without sudo you will see a partial picture and may wrongly conclude a port is unused.
- Prefer
-tfor scripts, but print before acting. Never pipelsof -tdirectly intokillwithout reviewing the PIDs first. A broad match can terminate the wrong service. - Avoid
+Don huge trees. Use+dor point at a specific file first. - Save evidence first. Redirect output to a timestamped file before you change anything on a suspect host.
- Cross-check with other tools. Compare lsof results with
ss -tulpnandps. Disagreements between tools are themselves a finding.
Related Cybersecurity Topics You Should Explore
- Linux pmap Command Cheat Sheet: 40 Examples for Memory Analysis
- Capcom Data Breach: 11.77M Records Exposed – Are You Safe?
- VeloCloud Orchestrator Flaw: Read-Only Login Gives Superuser
- 55 Linux Job Control Commands Every SOC Analyst Should Know
- PHP2Shell Patch Guide: Fix CVE-2026-109618 & 109619 Fast
- FortiSIEM CVE-2026-106173: Public PoC Drops, Patch Now
- Linux renice Command: 54 Examples to Control CPU Priority
- SBI Data Breach Claim: What's Real and What's Not
- Linux nice Command: 30 Examples to Protect Your Server CPU
FAQ
What does the lsof command do in Linux?
It lists files that running processes currently have open, including regular files, directories, network sockets, pipes, and devices. It is widely used to map a file or port back to the process using it.
How do I find which process is using a port?
Run sudo lsof -nP -i :8080, replacing 8080 with your port. Add -t if you only want the PID.
Why does lsof show nothing for some processes?
Usually permissions. Without root you can only see your own processes. Containers, namespaces, and kernel hardening options can also limit visibility.
What is the difference between +d and +D?
+d examines only files directly inside the named directory, while +D searches it recursively. The recursive form can be slow and I/O heavy on large trees.
How do I find deleted files that are still using disk space?
Use sudo lsof +L1. It lists open files with a link count below one, typically deleted files held open by a running process. Restarting or reloading the owning service releases the space.
Why did lsof -u alice -i show more than alice's sockets?
Selection options are ORed by default. Add -a (lsof -a -u alice -i) to require both conditions.
Is lsof better than netstat or ss?
They overlap. ss is faster for pure socket statistics, while lsof shines when you need to see everything else a process has open alongside its sockets. Using both is good practice.
Conclusion
lsof rewards the habit of asking "what is this process really doing?" It solves mundane problems, like the full disk with no visible files, and serious ones, like an unexplained listener on a production server. Learn the filtering logic (especially -a), make -nP a reflex, keep a baseline of normal listeners, and capture output before you change anything. Combined with logs and EDR telemetry, a handful of lsof commands will resolve a surprising share of your investigations quickly.
Analysis based on SOC monitoring experience and review of public Linux documentation. Replace example PIDs, usernames, hosts, and paths with real values, and test on non-production systems first.
