lsof, one lesson per page
Twenty-nine lessons for seeing every open file on a Linux system: the everything-is-a-file idea the tool is built on, the nine columns of its output and the FD codes inside it, who holds a port with -i and -sTCP:LISTEN, the -p, -c and -u process selectors, the OR-by-default and -a AND rules, +D and +L1 for directories and deleted-but-held files, -t for pipelines, and the repeat mode that watches a system change.
A diagram, the map, and one thing to try this week. That's a page.
lsof, one lesson per page
Twenty-nine lessons for seeing every open file on a Linux system: the everything-is-a-file idea the tool is built on, the nine columns of its output and the FD codes inside it, who holds a port with -i and -sTCP:LISTEN, the -p, -c and -u process selectors, the OR-by-default and -a AND rules, +D and +L1 for directories and deleted-but-held files, -t for pipelines, and the repeat mode that watches a system change.
Set in Space Grotesk, Inter and JetBrains Mono (SIL Open Font License).
Every fact in this book is as the official source states it, fetched and read during this build: the lsof(8) manual of upstream lsof revision 4.95.0, the same manual hosted by the Linux man-pages project at man7.org. Demand evidence from live beginner threads, reconfirmed at dispatch; no facts are sourced from tutorials, howtogeek, linuxize, Reddit or StackExchange. An independent guide, not affiliated with or endorsed by the lsof.org project.
Your purchase is for personal use only. You do not have redistribution rights: please do not share, resell, or republish this book or its pages.
© 2026 Steve Hodgkiss. All rights reserved. Personal use only; no redistribution rights.
Edition 1.0 · stevehodgkiss.net
Contents
Per lsof(8) DESCRIPTION: an open file may be a regular file, a directory, a block special file, a character special file, an executing text reference, a library, a stream or a network file (Internet socket, NFS file or UNIX domain socket); a specific file or all the files in a file system may be selected by path; in the absence of any options, lsof lists all open files belonging to all active processes.
Everything is a file
Per lsof(8), an open file may be any of eight things: a regular file, a directory, a device, executing program text, a library, a stream, an Internet socket or a UNIX domain socket.
That is the whole trick: the kernel tracks every one the same way, so one command names them all. In the absence of any options, lsof lists all open files belonging to all active processes.
When someone says a socket is not really a file, lsof is the rebuttal.
This week, run plain lsof as your own user in one terminal and count how many of the eight open-file kinds appear.
Per lsof(8) OUTPUT, the FD column: FD is the File Descriptor number of the file, or codes including cwd current working directory, err FD information error, ltx shared library text, mem memory-mapped file, mmap memory-mapped device, rtd root directory, txt program text (code and data); FD is followed by a mode character (r, w, u, space, dash) and then a lock character.
Read the FD column
FD is two stories in one cell. A number is the descriptor slot: 4u means slot 4, opened for read and write.
A word is a special hold, per lsof(8): cwd the working directory, txt the program text, mem a memory-mapped file, rtd the root directory, err an information error.
Read the cell as slot plus manner and no line of lsof output is cryptic again.
Pick one process with lsof -p this week and sort its FD column in your head: which slots are files, which are codes?
Per lsof(8) -s [p:s]: to list only network files with TCP state LISTEN, use -iTCP -sTCP:LISTEN; per the -i description and EXAMPLES, lsof -i 4 -a -p 1234 lists open IPv4 network files in use by PID 1234; per OUTPUT, NAME for a network file is the local address, colon, port, an arrow, then the two-part remote address, with zero ports shown as an asterisk.
Who holds this port
Address already in use has one answer. Per lsof(8), -iTCP -sTCP:LISTEN lists only network files with TCP state LISTEN, and adding the port narrows it to one socket.
In the NAME cell, *:22 reads as all interfaces, port 22: the asterisk marks a zero port or wildcard address, per the OUTPUT section. The PID column is your culprit.
Port number to process, one command, no guessing. This page alone pays for the book.
The next time a service will not bind, run lsof -nP -iTCP:PORT -sTCP:LISTEN this week and read the PID before you search the web.
Per lsof(8) OPTIONS: the -a option may be used to AND the selections; specifying -a, -U, and -ufoo produces a listing of only UNIX socket files that belong to processes owned by user foo; caution: the -a option causes all list selection options to be ANDed; it can't be used to cause ANDing of selected pairs of selection options by placing it between them, even though its placement there is acceptable; wherever -a is placed, it causes the ANDing of all selection options.
Ask for the AND
-a is the ask: per lsof(8), -a, -U, -ufoo lists only UNIX socket files that also belong to user foo. The intersection, not the union.
The caution is worth quoting: -a ANDs all selection options, wherever you place it. It cannot be slipped between two options to AND just that pair.
One -a flips the tool from generous to strict, for everything at once.
Turn last lesson's two-selector command strict this week: add -a and watch the crowd become the overlap.
Per lsof(8) +|-L [l]: when +L is followed by a number, only files having a link count less than that number will be listed, and a specification of the form +L1 will select open files that have been unlinked; a specification of the form +aL1 will select unlinked open files on the specified file system; the TYPE column includes DEL for a Linux map file that has been deleted.
Deleted but not gone
rm removes the name. The space returns only when the last holder closes the file. Until then, df counts it and du cannot see it: the disk is full with no large files anywhere.
Per lsof(8), +L1 lists open files that have been unlinked, files whose link count has fallen under one. There they are, with PIDs.
The mystery disk is usually one giant deleted log still held by a service that was never restarted.
The next time a disk is full and du finds nothing, run lsof +L1 this week before anything else.
Per lsof(8): in the absence of any options lsof lists all open files belonging to all active processes; a specific file or all the files in a file system may be selected by path; -i [i] selects by Internet address; -p s, -c c and -u s select by process, command and user; +d and +D search directories; +L1 selects unlinked open files; -t produces PIDs only; the EXAMPLES range from bare lsof through kill -HUP with lsof -t.
One habit to keep
Every real question is three shapes: what is held, who holds it, how. A path argument or -i names the what. PID and COMMAND are the who. FD and TYPE are the how.
Per lsof(8), the same command does all three: selections by path, by address, by process, command, user, directory and link count.
Ask what, read who, note how. That loop is the whole tool, and it never changes shape.
Take one real mystery this week, name which of the three questions it is, and let that choose your flags.