# Listing Open File Descriptors - Shell Scripting

With only nine file descriptors available to you, you’d think that it wouldn’t be too hard keeping things straight. Sometimes, though, it’s easy to get lost when trying to keep track of which file descriptor is redirected where. To help you keep your sanity, the bash shell provides the lsof command.

The lsof command lists all of the open file descriptors on the entire Linux system. This is somewhat of a controversial feature, as it can provide information about the Linux system to non-system-administrators. Because of this, many Linux systems hide this command so that users don’t accidentally stumble across it.

On my Fedora Linux system, the lsof command is located in the /usr/sbin directory. To run it with a normal user account, I have to reference it by its full pathname:

$/usr/sbin/lsof This produces an amazing amount of output. It displays information about every file currently open on the Linux system. This includes all of the processes running on background, as well as any user accounts logged in to the system. There are plenty of command line parameters and options available to help filter out the lsof output. The most commonly used are -p, which allows you to specify a process ID (PID), and -d, which allows you to specify the file descriptor numbers to display. To easily determine the current PID of the process, you can use the special environment variable $$, which the shell sets to the current PID. The -a option is used to AND the results of the other two options, to produce the following: /usr/sbin/lsof -a -p$$ -d 0,1,2 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME bash 3344 rich 0u CHR 136,0 2 /dev/pts/0 bash 3344 rich 1u CHR 136,0 2 /dev/pts/0 bash 3344 rich 2u CHR 136,0 2 /dev/pts/0$

This shows the default file descriptors (0, 1, and 2) for the current process (the bash shell). The default output of lsof contains several columns of information, described in Table below.

Table:Default lsof Output

The file type associated with STDIN, STDOUT, and STDERR is character mode. Since the STDIN, STDOUT, and STDERR file descriptors all point to the terminal, the name of the output file is the device name of the terminal. All three standard files are available for both reading and writing (although it does seem odd to be able to write to STDIN and read from STDOUT).Now, let’s take a look at the results of the lsof command from inside a script that’s opened acouple of alternative file descriptors:

$cat test18 #!/bin/bash # testing lsof with file descriptors exec 3test18file1 exec 6test18file2 exec 7testfile /usr/sbin/lsof -a -p$$-d0,1,2,3,6,7$ ./test18 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
test18 3594 rich 0u CHR 136,0 2 /dev/pts/0
test18 3594 rich 1u CHR 136,0 2 /dev/pts/0
est18 3594 rich 2u CHR 136,0 2 /dev/pts/0
18 3594 rich 3w REG 253,0 0 360712 /home/rich/test18file1
18 3594 rich 6w REG 253,0 0 360715 /home/rich/test18file2
18 3594 rich 7r REG 253,0 73 360717 /home/rich/testfile
\$

The script creates three alternative file descriptors, two for output (3 and 6) and one for input (7). When the script runs the lsof command, you can see the new file descriptors in the output. I truncated the first part of the output so that you could see the results of the file name. The filename shows the complete pathname for the files used in the file descriptors. It shows each of the files as type REG, which indicates that they are regular files on the filesystem.