在当前bash会话中列出打开的文件描述符
1. 简介
在使用 bash shell 时,我们的 shell 进程可能会因为多种原因而出现各种打开的文件。这些打开的文件每个都有一个相应的文件描述符整数,Linux 的用户空间在通过系统调用或库调用与内核空间通信时使用该整数来标识特定文件。
在本教程中,我们将讨论如何从 bash 会话本身中查看该 bash 会话的打开文件描述符。
2. 使用ls
我们可以使用ls 命令列出给定目录中的目录和文件。此外,内核通过** proc伪文件系统导出有关 Linux 系统上所有正在运行的进程的信息**。
默认情况下,这个文件系统几乎总是挂载在*/proc上。我们可以利用/proc下导出的信息并将其与ls*命令结合起来,列出进程的打开文件描述符。
在*/proc伪文件系统中,我们可以在/proc/pid/fd/*下找到打开的文件描述符,其中 pid 是给定进程的 PID。因此,我们必须确定进程的进程标识号 (PID) 才能查看其打开的文件描述符。*要获取 bash 会话进程的 PID,我们使用$$*表达式。*当我们在 bash 命令中使用$$*表达式时,它会扩展为当前 bash 会话的 PID。
因此,我们可以使用ls命令和*$$*表达式来显示当前 bash 会话的文件描述符以及它们引用的文件:
$ 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. 使用lsof
lsof 命令列出有关系统上正在运行的进程的打开文件的信息。 当我们不带任何参数运行lsof时,它会显示系统上运行的每个进程的打开文件。这也将使lsof以“重复”模式运行,这将导致输出循环。但是,我们不必过多担心重复模式,因为以下命令会阻止这种情况。
我们可以告诉lsof只列出 bash 会话进程的打开文件,方法是使用*-p*选项和我们与ls一起使用的$$ shell 表达式:
$ 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
我们从输出中看到,前面的命令包含的打开文件比我们的文件描述符引用的要多。
为了解决这个问题,我们可以通过指定从 0 到 INT_MAX 的范围使lsof只显示数字文件描述符。
因此,我们在下一个示例中使用*-d选项来指定文件描述符的范围。同样,我们使用-p选项来指定 PID。然后我们将它与-a*选项结合起来,将这些选择“和”(或组合)在一起:
$ 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