Updated: May 12, 2010
lsof is one of the more important tools you can use on your Linux box. Its name is somewhat misleading. lsof stands for list open files, but the term files fails to impact the true significance of power. That is, unless you remember the fundamental lesson, in Linux everything is a file.
We have had several super-duper admin articles, focusing around tools that help us understand better the behavior of our system, try to identify performance bottlenecks and solve issues that do not have an apparent, immediate presence in the logs. Save for vague, indirect symptoms, you might be struggling to understand what is happening under the hood.
lsof, alongside strace and OProfile, is another extremely versatile, powerful weapon in the arsenal of a system administrator and the curious engineer. Used correctly, it can yield a wealth of information about your machine, helping you narrow down the problem solving and maybe even expose the culprit.
So let's see what this cool tool can do.
Why is lsof so important?
I did say lsof is important, but I did not say why. Well, the thing is, with lsof you can do pretty much anything. It encompasses the functionality of numerous other tools that you may be familiar with.
For example, lsof can provide the same information netstat offers. You can use lsof to find mounts on your machine, so it supplements both /etc/mtab and /proc/mounts. You can use lsof to learn what open files a processes holds. In general, pretty much anything you can find under the /proc filesystem, lsof can display in a very simple, centric manner, without writing custom scripts for looping through the sub-directories and parsing and filtering content.
lsof allows you to display information for particular users, processes, show only traffic for certain network protocols, file handles, and more. Used effectively, it's the Swiss Knife of admin utilities.
lsof in action
A few demonstrations are in order.
Run without any parameters, lsof will display all of the information for all of the files. At this point, I should reiterate the fact there are many types of files. While most uses treat their music and Office documents as files, the generic description goes beyond that. Devices, sockets, pipes, and directories are also files.
lsof output explained
Before we dig in, let's take a look at a basic output:
Command is the name of the process. It also includes kernel threads. PID is the process ID. USER is the owner of the process. FD is the first truly interesting field.
The FD stands for File Descriptor, an abstract indicator for accessing of files. File descriptors are indexes in kernel data structures called file descriptor tables, which contain details of all open files. Each process has its file descriptor table. User applications that wish to read and write to files will instead read to and write from file descriptors using system calls. The exact type of the file descriptor will determine what the read and write operations really mean.
In our example, we have several different values of FD listed. If you have ever looked under the /proc filesystem and examined the structure of a process, some of the entries will be familiar. For instance, cwd stands for Current Working Directory of the listed process. txt is the Text Segment or the Code Segment (CS), the bit of the object containing executable instructions, or program code if you will. mem stands for Data Segments and Shared Objects loaded into the memory. 10u refers to file descriptor 10, open for both reading and writing. rtd stands for root directory.
As you can see, you need to understand the output, but once you get the hang of it, it's a blast. lsof provides a wealth of information, formatted for good looks, without too much effort. Now, it's up to you to put the information to good use.
The fifth column, TYPE is directly linked to the FD column. It tells us what type of file we're working with. DIR stands for directory. REG is a regular file or a page in memory. FIFO is a named pipe. Symbolic links, sockets and device files (block and character) are also file types. unknown means that the FD descriptor is of unknown type and locked. You will encounter these only with kernel threads.
For more details, please read the super-extensive man page.
Now, we're already having a much better picture of what lsof tells us. For instance, 10u is a pipe used by initctl, a process control initialization utility that facilitates the startup of services during bootup. All in all, it may not mean anything at the moment, but if and when you have a problem, the information will prove useful.
The DEVICE column tells us what device we're working on. The two numbers are called major and minor numbers. The list is well known and documented. For instance, major number 8 stands for SCSI block device. For comparison, IDE disks have a major number 3. The minor number indicates one of the 15 available partitions. Thus (8,1) tell us we're working on sda1.
(0,16), the other interesting device listed refers to unnamed, non-device mounts.
For detailed list, please see:
SIZE/OFF is the file size. NODE is the Inode number. Name is the name of the file. Again, do not be confused. Everything is a file. Even your computer monitor, only it has a slightly different representation in the kernel.
Now, we know everything. OK, unfiltered output is too much to digest in one go. So let's start using some flags for smart filtering of information.
To see all the open files a certain process holds, use -p:
lsof -p <pid>
Similarly, you can see files per user using the -u flag:
lsof -u <name>
You can see all the processes holding a certain fie descriptor with -d <number>:
lsof -d <number>
This is very important if you have hung NFS mounts or blocked processes in uninterruptible sleep (D state) refusing to go away. Your only way to start solving the problem is do dig into lsof and trace down the dependencies, hopefully finding processes and files that can be killed and closed. Alternatively, you can also display all the open file descriptors:
Notice that the number is rising in sequence. In general, Linux kernel will give the first available file descriptor to a process asking for one. The convention calls for file descriptors 0, 1 and 2 to be standard input (STDIN), standard output (STDOUT) and standard error (STDERR), so normally, file descriptor allocation will start from 3.
If you've ever wondered what we were doing when we devnull-ed both the standard output and the standard error in the strace examples, this ought to explain it. We had the following:
something > /dev/null 2>&1
In other words, we redirected standard output to /dev/null, and then we redirected file descriptor 2 to 1, which means standard error goes to standard output, which itself is redirected to the system black hole.
Finding file descriptors can be quite useful, especially if some applications are hard-coding their use, which can lead to problems and conflicts. But that's a different story altogether.
One more thing notable from the above screenshot are the unix and CHR FD types, which we have not yet seen. unix stands for UNIX domain socket, an interprocess communication socket, similar to Internet sockets, only without using a network protocol. CHR stands for a character device. Character devices allow the transmission of a single bit of data; typical examples are terminals, keyboard, mouse, and similar peripherals, where the order of data is critical.
Do not confuse domain sockets with classic sockets, which is an end-point consisting of an IP address and a port.
lsof can also provide lots of information similar and identical to netstat. You can dump the listing of all files and then grep for relevant information, like LISTEN, ESTABLISHED, IPV4, or any other network related term.
Internet protocols & ports
Specifically, lsof can also show you the open ports for either IPv4 or IPv6 protocols, much like nmap scan against the localhost:
lsof also supports a number of flags that are enabled with + and disabled with - signs, rather than the typical use of single or double dash (-) characters as option separators.
One of these is +d (and +D), which lets you show all the processes holding a certain directory. The capital D also lets you recurse and expands all the files in the directory and its sub-directories, whereas lower d will just show the directories and no files.
lsof +d <dir name> or lsof +D <dirname>
I've given you two juicy examples when I wrote the strace tutorial. I skimped a bit with OProfile, because finding simple and relevant problems that can be quickly demonstrated with a profiler tool are not easy to come by - but do not despair, there shall be an article.
Now, lsof allows a plenty of demo space. So here's one.
How do you handle a stuck mount?
Let's say you have a mount that refuses to go down. And you don't really know what's wrong. For some reason, it won't let you unmount it.
You tried the umount command, but it does not really work:
Luckily for you, openSUSE recommends using lsof, but let's ignore that for a moment.
Anyhow, your mount won't come down. In desperation and against better judgment, you also try forcing the unmounting of the mount point with -f flag, but it still does not help. Not only the mount is refusing to let go, you may have also corrupted the /etc/mtab file by issuing the force mount command. Just some food for thought.
Now, how do you handle this?
The hard way
If you're experienced and know your way about /proc, then you can do the following:
Under /proc, examine the current working directories and file descriptors holding the mount point. Then, examine the process table and see what the offending processes are and if they can be killed.
ls -l /proc/*/cwd | grep just
ls -l /proc/*/fd | grep just
Finally, in our example:
ps -ef | grep -E '10878|10910'
And problem solved ...
Note: sometimes, especially if you have problems with mounts or stuck processes, lsof may not be the best tool, as it too may get stuck trying to recurse. In these delicate cases, you may want to use the -n and -l flags. -n inhibits the conversion of network IP addresses to domain names, making lsof work faster and avoids lockups due to name lookup not working properly. -l inhibits conversion of user IDs to names, quite useful if name lookup is working slowly or improperly, including problems with nscd daemon, connectivity to NIS, LDAP or whatever, and other issues. However, sometimes, in extreme cases, going for /proc may be the most sensible option.
The easy (and proper) way
By the book, using lsof ought to do it:
lsof | grep just
And problem solved. Well, we still need to free the mount by closing or killing the process and the files held under the mount point, but we know what to do. Not only do we get all the information we need, we do this quickly, efficiently.
Knowing the alternative methods is great, but you should always start smart and simple, with lsof, exploring, narrowing down possibilities and converging on the root cause.
I hope you liked it.
All of the following articles should be useful in building your Linux knowledge:
Linux super-duper admin tools: screen (another useful utility)
Of course, you're most welcome to peruse the entire Linux section, as it contains hundreds of tutorials and how-tos on many subjects. On the high-end of computing, you should start with the listed selection, explore strace and OProfile and then take a look at the Linux kernel crash collection and analysis series. It's all there.
There you go,a wealth of information about lsof and what it can do for you. I bet you won't easily find detailed explanation about lsof output elsewhere, although examples about the actual usage are aplenty. Well, my tutorial provides you with both.
Now, the big stuff is ahead of you. Using lsof to troubleshoot serious system problems, without wasting time going through /proc and trying to find relevant system information, when it's all there, hidden under just one mighty command.
That would be. Stay tuned for more super-duper tools!