1. Introduction

When using the bash shell, the process of our shell may come to have various open files for many reasons. These open files each have a corresponding file descriptor integer that Linux’s User space uses to identify the specific file when communicating with Kernel space via system calls or library calls.

In this tutorial, we’re going to discuss how to view the open file descriptors of a bash session from within that bash session itself.

2. Using ls

We can use the ls command to list directories and files within a given directory. Also, the kernel exports information about all of the running processes on a Linux system via the proc pseudo filesystem.

This filesystem is almost always mounted at /proc by default. We can take advantage of the information exported under /proc and combine it with the ls command to list the open file descriptors of a process.

In the /proc pseudo filesystem, we can find the open file descriptors under /proc//fd/ where is the PID of a given process. Thus, we have to determine the process identification number (PID) of a process to look at its open file descriptors. To get the PID of our bash session’s process, we use the $$ expression. When we use the $$ expression in a bash command, it expands to the PID of the current bash session.

Thus, we can use the ls command and the $$ expression to display the file descriptors of the current bash sessions and the files that they refer to:

$ ls -la /proc/$$/fd/
total 0
dr-x------ 2 user user  0 Apr  7 17:14 .
dr-xr-xr-x 9 user user  0 Apr  7 17:14 ..
lrwx------ 1 user user 64 Apr  7 17:14 0 -> /dev/pts/50
lrwx------ 1 user user 64 Apr  7 17:14 1 -> /dev/pts/50
lrwx------ 1 user user 64 Apr  7 17:14 2 -> /dev/pts/50
lrwx------ 1 user user 64 Apr  7 17:14 255 -> /dev/pts/50
lr-x------ 1 user user 64 Apr  7 17:14 3 -> /tmp/testfile2
l-wx------ 1 user user 64 Apr  7 17:14 4 -> /tmp/testfile1

3. Using lsof

The lsof command lists information about open files for running processes on the system.

When we run lsof without any arguments, it displays the open files of every process running on the system. This will also make lsof run in “repeat” mode, which will cause the output to loop. However, we don’t have to worry about repeat mode too much, as the following commands will prevent that.

We can tell lsof to only list the open files of our bash session’s process by using the -p option in combination with the $$ shell expression that we used with ls:

$ lsof  -p $$
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
bash    14928 user  cwd    DIR  252,1     4096  4060 /tmp
bash    14928 user  rtd    DIR  252,1     4096     2 /
bash    14928 user  txt    REG  252,1  1113504    32 /bin/bash
bash    14928 user  mem    REG  252,1    47568 26949 /lib/x86_64-linux-gnu/libnss_files-2.27.so
bash    14928 user  mem    REG  252,1    97176 26946 /lib/x86_64-linux-gnu/libnsl-2.27.so
bash    14928 user  mem    REG  252,1    47576 26951 /lib/x86_64-linux-gnu/libnss_nis-2.27.so
bash    14928 user  mem    REG  252,1    39744 26947 /lib/x86_64-linux-gnu/libnss_compat-2.27.so
bash    14928 user  mem    REG  252,1  1516558 30707 /usr/lib/locale/C.UTF-8/LC_COLLATE
bash    14928 user  mem    REG  252,1  2030928 26939 /lib/x86_64-linux-gnu/libc-2.27.so
bash    14928 user  mem    REG  252,1    14560 26942 /lib/x86_64-linux-gnu/libdl-2.27.so
bash    14928 user  mem    REG  252,1   170784  2104 /lib/x86_64-linux-gnu/libtinfo.so.5.9
bash    14928 user  mem    REG  252,1   179152 26935 /lib/x86_64-linux-gnu/ld-2.27.so
bash    14928 user  mem    REG  252,1   199772 30708 /usr/lib/locale/C.UTF-8/LC_CTYPE
bash    14928 user  mem    REG  252,1       50 30720 /usr/lib/locale/C.UTF-8/LC_NUMERIC
bash    14928 user  mem    REG  252,1     3360 30724 /usr/lib/locale/C.UTF-8/LC_TIME
bash    14928 user  mem    REG  252,1      270 30715 /usr/lib/locale/C.UTF-8/LC_MONETARY
bash    14928 user  mem    REG  252,1       48 30714 /usr/lib/locale/C.UTF-8/LC_MESSAGES/SYS_LC_MESSAGES
bash    14928 user  mem    REG  252,1       34 30722 /usr/lib/locale/C.UTF-8/LC_PAPER
bash    14928 user  mem    REG  252,1  1683056  4354 /usr/lib/locale/locale-archive
bash    14928 user  mem    REG  252,1       62 30718 /usr/lib/locale/C.UTF-8/LC_NAME
bash    14928 user  mem    REG  252,1      131 30705 /usr/lib/locale/C.UTF-8/LC_ADDRESS
bash    14928 user  mem    REG  252,1       47 30723 /usr/lib/locale/C.UTF-8/LC_TELEPHONE
bash    14928 user  mem    REG  252,1       23 30713 /usr/lib/locale/C.UTF-8/LC_MEASUREMENT
bash    14928 user  mem    REG  252,1    26376 27208 /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache
bash    14928 user  mem    REG  252,1      252 30709 /usr/lib/locale/C.UTF-8/LC_IDENTIFICATION
bash    14928 user    0u   CHR 136,50      0t0    53 /dev/pts/50
bash    14928 user    1u   CHR 136,50      0t0    53 /dev/pts/50
bash    14928 user    2u   CHR 136,50      0t0    53 /dev/pts/50
bash    14928 user    3r   REG  252,1        5   150 /tmp/testfile2
bash    14928 user    4w   REG  252,1        0  2230 /tmp/testfile1
bash    14928 user  255u   CHR 136,50      0t0    53 /dev/pts/50

We see from the output that the previous command includes more open files than those that our file descriptors reference.

To address this, we can make lsof only show numeric file descriptors by specifying a range from 0 to INT_MAX.

Thus, we use the -d option to specify a range of file descriptors in the next example. Again, we use the -p option to specify the PID. We then combine this with the -a option to “and” (or combine) these selections together:

$ lsof -a -d 0-2147483647 -p $$
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
bash    14928 user    0u   CHR 136,50      0t0   53 /dev/pts/50
bash    14928 user    1u   CHR 136,50      0t0   53 /dev/pts/50
bash    14928 user    2u   CHR 136,50      0t0   53 /dev/pts/50
bash    14928 user    3r   REG  252,1        5  150 /tmp/testfile2
bash    14928 user    4w   REG  252,1        0 2230 /tmp/testfile1
bash    14928 user  255u   CHR 136,50      0t0   53 /dev/pts/50

4. Conclusion

In this article, we’ve learned that we can use both the ls and lsof commands to list the open file descriptors in the current bash session. We can use the ls command to parse /proc manually and display our open file descriptors. Alternatively, we can leave it up to lsof and provide the PID of the current bash session.