lsof [options] [names]
sudo lsof -i :80
lsof means "list open files". On Linux, almost everything is a file: regular files,
directories, devices, pipes and network sockets. So lsof can answer questions like
"what is using port 8080?", "who has this file open?" and "why can't I unmount this drive?".
Run it with sudo to see other users' processes. Without sudo you only see your own.
Read the output
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 1234 root 6u IPv4 12345 0t0 TCP *:80 (LISTEN)
COMMAND Program name (truncated to 9 characters by default) PID Process ID
USER Owner NODE Inode or protocol
FD File descriptor: cwd (current dir), txt (program), mem (mapped), 0u/1u/2u (stdin/out/err),
3r read, 4w write, 5u read+write, and numbers for other open files
TYPE REG file, DIR directory, CHR device, FIFO pipe, IPv4/IPv6 socket, unix local socket
NAME The file path or the network address
Files
lsof /var/log/syslog # who has this file open?
lsof /path/to/dir # who has this specific directory open?
lsof +D /var/log # everything open under a directory (recursive; slow)
lsof +d /var/log # one level only
lsof /dev/sda1 # who is using a device?
lsof /mnt/usb # why won't this drive unmount?
lsof | grep deleted # deleted files still held open (they still use disk space)
lsof +L1 # open files with zero links (deleted but not freed)
lsof -c nginx # files opened by commands starting with "nginx"
lsof -c ssh -c sshd # several commands
Users and processes
lsof -u alice # files opened by user alice
lsof -u ^root # every user EXCEPT root
lsof -u alice,bob
lsof -p 1234 # files opened by PID 1234
lsof -p ^1234 # everything except that PID
lsof -g 1000 # by process group
lsof -a -u alice -c firefox # -a = AND: alice's firefox files only
Options combine with OR by default. Add -a to require all conditions.
Network connections
lsof -i # all network files (TCP and UDP)
lsof -i 4 # IPv4 only lsof -i 6 IPv6 only
lsof -i TCP # TCP only lsof -i UDP UDP only
lsof -i :80 # who uses port 80?
lsof -i :80,443 # several ports
lsof -i :8000-9000 # a port range
lsof -i TCP:22 # TCP port 22
lsof -i @192.168.1.10 # connections to or from a host
lsof -i @192.168.1.10:22 # to a host and port
lsof -i TCP -s TCP:LISTEN # only listening TCP sockets
lsof -i TCP -s TCP:ESTABLISHED # only established connections
lsof -iTCP -sTCP:LISTEN -P -n # listening ports, numeric (no DNS, no service names)
lsof -u alice -i # alice's network connections
lsof -p 1234 -i # network files of one process
lsof -i -a -c nginx # nginx's network sockets only
lsof -U # Unix domain sockets
Useful display options
-P Show port numbers instead of service names (443, not https)
-n Do not resolve hostnames (much faster)
-l Show user IDs instead of names
-t Terse: print PIDs only (great for kill and scripts)
-r 2 Repeat every 2 seconds (until Ctrl+C)
-F Machine-readable fields output
-w Suppress warnings -V Verbose about why a search found nothing
-H Human-readable sizes (newer versions)
+c 0 Show the full command name
Good default: sudo lsof -nP -i
Practical one-liners
# What is listening on port 8080, and which program?
sudo lsof -nP -iTCP:8080 -sTCP:LISTEN
# Every listening TCP port on this machine
sudo lsof -nP -iTCP -sTCP:LISTEN
# Kill whatever is using port 3000 (check first!)
sudo lsof -t -i :3000 | xargs -r sudo kill
# See what a program is talking to
sudo lsof -nP -a -i -c firefox
# Find the disk hog: deleted-but-open files still using space
sudo lsof -nP +L1
# Why can't I unmount /mnt/data?
sudo lsof +f -- /mnt/data
sudo lsof +D /mnt/data
# Files a process has open right now
sudo lsof -p $(pgrep -o nginx)
# How many files does a process have open? (compare with its ulimit -n)
sudo lsof -p 1234 | wc -l
# Open files per process, biggest first (find file descriptor leaks)
sudo lsof -n | awk '{print $1, $2}' | sort | uniq -c | sort -rn | head
# Watch connections from one host live
sudo lsof -nP -i @10.0.0.5 -r 2
# What is using the current directory of a user's shell?
sudo lsof -a -u alice -d cwd
# What has a specific file descriptor open?
sudo lsof -d 3
# Reclaim disk space from a deleted log without restarting the service (careful)
sudo truncate -s 0 /proc/1234/fd/5
Related tools
ss -tulpn Listening sockets, faster than lsof -i on busy servers
fuser -v /path Who is using a file or mount (short answer)
fuser -k 80/tcp Kill whatever uses port 80 (use carefully)
netstat -tulpn The older tool for listening ports
ls -l /proc/PID/fd The open files of a process, straight from /proc
pgrep / pidof Find PIDs by name
Common problems
Output is empty Try sudo. Without root you only see your own processes
Runs very slowly Use -n -P (no DNS or port name lookups) and avoid +D on big trees
"can't stat() ... file system" A warning about mounts you cannot read: add -w or ignore it
+D on huge directories hangs Use a specific path, or +d for one level, or fuser
COMMAND names are cut off Use +c 0 to show the full name
Nothing on the port I expected The app may listen on another port, or on IPv6 only: try lsof -i 6
Disk is full but du disagrees Deleted files still held open: lsof +L1, then restart the holder
Tips
Use sudo, or you will miss most of the picture. Without it lsof only shows your own processes.
Add -nP to network searches so it does not stop to resolve names.
Use -t to get bare PIDs for scripting, and always check what you are about to kill.
"df says full, du says empty" almost always means deleted files that a process still has open. Find them with lsof +L1.
Use -a when you want conditions ANDed. By default lsof ORs them and shows more than you asked for.
For a quick "what is listening" answer, ss -tulpn is faster. Use lsof for "what does this process or file touch".
Use -r to repeat, watching a connection or file until it appears or disappears.
Compare a process's open file count with ulimit -n to catch descriptor leaks before they crash a service.