The lsof command lists every file a process has open — and on Linux that includes sockets, pipes and devices. If a port is busy, a log file will not rotate, or a disk stays full after you delete files, lsof tells you which process is responsible. This guide walks through the commands that answer those questions fast, on Ubuntu, Debian, AlmaLinux and Rocky.
Before you start
You need SSH access to the VPS and a user that can run commands with sudo. lsof only shows other users' processes when you run it as root, so prefix almost everything here with sudo.
Check what you have:
lsb_release -a 2>/dev/null || cat /etc/os-release
lsof -vIf lsof -v prints nothing, install it:
sudo apt update && sudo apt install -y lsof # Ubuntu 22.04/24.04, Debian 12
sudo dnf install -y lsof # AlmaLinux / Rocky 8-9Tip: Always add -n (no DNS lookups) and -P (no port-name lookups) to network queries. On a busy VPS those two flags turn a 30-second wait into instant output.
Run your first listing
Bare lsof dumps everything, which is noisy. Start with a count so you know how much is open:
sudo lsof -nP | wc -l
sudo lsof -u deploy -nP | wc -lThe columns you care about:
COMMANDandPID— the process name and its process ID.USER— who owns it.FD— the file descriptor type:cwd(current directory),txt(executable),mem(memory-mapped), a number for data files.TYPE—REGfor regular file,DIR,IPv4,IPv6,unix.NAME— the path, or the socket address inlocal:remoteform.
To see one process in full rather than truncated names:
sudo lsof -p 4821
sudo lsof -p 4821 +c 0Find which process is using a port
This is the most common reason people reach for lsof — a service refuses to start with "Address already in use".
sudo lsof -nP -i :80
sudo lsof -nP -i :443To list only listeners:
sudo lsof -nP -i -sTCP:LISTENTo check whether a specific process opened a connection outbound:
sudo lsof -nP -i TCP -a -c nginxThe -a operator is important: it ANDs the filters together instead of ORing them. Without it you get every nginx file plus every TCP socket on the box.
When you only want process IDs, for example to feed into another command:
sudo lsof -t -i :8080Warning: Never run kill -9 on a process just because it holds a port. Stop it properly first (sudo systemctl stop <service>) so it flushes state and releases its lock files.
Find which process holds a file open
To see what is using a single file:
sudo lsof /var/log/syslogTo scan a whole directory tree, for example before unmounting a volume:
sudo lsof +D /var/www
sudo lsof +D /mnt/data+D recurses and can be slow on large trees. +d checks only the directory itself.
If a user cannot empty their home directory because something is holding files, filter by user and path together:
sudo lsof -u deploy -nP +d /home/deployReclaim disk space held by deleted files
A process that keeps a log file open after you delete it still occupies the inode, so df reports the disk as full. That is why deleting a big log sometimes frees nothing. Find those files:
sudo lsof -nP +L1Look for a LINK count below 1 and a large SIZE/OFF, with NAME ending in (deleted). A common case is a rotated Nginx or PHP-FPM log held by a worker:
nginx 2211 www-data 4w REG 253,0 4123456789 131074 /var/log/nginx/access.log (deleted)The fix is to make the process reopen its files, not to delete more files:
sudo systemctl reload nginx
sudo systemctl restart php8.3-fpm # adjust to your PHP versionWarning: Do not truncate a deleted file through /proc/<pid>/fd unless you are certain nothing is writing to it. On a live log you can lose buffered data and confuse the application's offset tracking.
Handle "too many open files"
When a service throws EMFILE: too many open files, count what it actually holds:
sudo lsof -u www-data -nP | wc -l
sudo lsof -p $(pgrep -f 'php-fpm: pool www' | head -1) | wc -lCompare that with the limit in force:
cat /proc/$(pgrep -f 'php-fpm: master' | head -1)/limits | grep -i 'open files'If the count sits near the limit, raise it in the systemd unit rather than only in limits.conf:
[Service]
LimitNOFILE=65535Then reload and restart:
sudo systemctl daemon-reload
sudo systemctl restart php8.3-fpmNote: lsof is a snapshot, not a monitor. Run it two or three times a minute apart to confirm a file descriptor count is genuinely climbing.
Check it works
Pick a listening port you know is in use, such as SSH on 22:
sudo lsof -nP -i :22You should see the sshd process, its PID and a LISTEN state. Now confirm the same PID appears for that user:
sudo lsof -u root -nP | grep LISTEN | headThen verify the deleted-file check runs cleanly on a quiet system — no output means nothing is holding an unlinked file open, which is normal:
sudo lsof -nP +L1If all three behave as described, lsof is installed and you are reading it correctly. You can also confirm resource pressure from your VPS provider's control panel, where the browser console and power controls let you act on a service that will not respond over SSH.
Troubleshooting
lsof: command not found— the package is missing. Installlsofwithaptordnfas shown above; some minimal cloud images ship without it.lsofhangs or takes minutes — it is resolving names and scanning large trees. Add-nP, narrow with-p,-uor+dinstead of+D, and avoid running it against NFS mounts when they are unresponsive.- A port responds but
lsofshows nothing — either you are not root, or the socket belongs to a container in its own network namespace. Runsudo lsof -nP -iinside the container, or compare againstss -tulpnon the host. - Command names are cut off, so you cannot tell two workers apart — use
sudo lsof +c 0 -p <pid>to print full command lines. lsofreports "can't stat" or permission denied on some entries — expected for paths you cannot read. Anything you truly need will appear when you run it withsudo.
Next steps
- Cross-check connections with Using netstat and ss for detailed network connection analysis on Linux when you need live socket states rather than a snapshot.
- Freeing an inode is only half the job — see Fix "No space left on device" when the disk isn't full (inodes) for the full procedure.
- If
lsof +L1keeps showing the same process, Automating server restarts and health checks with systemd services shows how to recycle it on a schedule. - Heavy file activity from one worker usually means I/O pressure — tune it with Optimizing disk I/O on a VPS: tuning mount options and swap.
