在 的输出中lsof
,该列是否始终输出打开文件的已解析绝对路径名(在无符号链接或路径名NAME
的意义上解析)?.
..
例如,如果我cd
进入某个目录的符号链接,然后运行程序来打开该目录下的文件,是否lsof
只显示该文件的解析绝对路径名?
我可以lsof
输出已打开文件的未解析的绝对路径名(未解析的意思是目录符号链接应该出现在路径名中)吗?
谢谢。
答案1
如果没有选项,它应该以解析的形式提供路径名。从lsof(8) 手册:
打开的文件可以是常规文件、目录、块特殊文件、字符特殊文件、执行文本引用、库、流或网络文件(Internet 套接字、NFS 文件或 UNIX 域套接字)。可以通过路径选择文件或文件系统中的所有文件。
当然也可能有错误,比如路径名太长,在这种情况下,路径名不会被解析,但在其他方面lsof
显然依赖于周围的包装函数readlink()
,应该可以完成这项工作。
如果您确实指定了一个文件名,如lsof [options] [--] names
,它应该被解析:
名称 这些是要列出的特定文件的路径名。符号链接在使用前已解析。可以使用“--”选项将名字与前面的选项分隔开。
当然,解析文件名的标准规则适用。符号链接级别太多会导致错误。lsof
依赖于 MAXSYMLINKS 变量 在 Linux 内核中硬编码至最大级别 40 个符号链接, 和对于变量未定义的其他系统 - 将其设置为 32。
如果您指定-b
选项,则不会解析文件名:
第三,如果 lsof 从系统挂载表获取的文件系统目录名称是符号链接,则 lsof 将无法解析这些链接。这是因为 -b 选项导致 lsof 避免使用它用来解析符号链接的内核 readlink(2) 函数。
答案2
我不知道正在使用的套接字文件是否应算作打开文件,但在 unix 域套接字的情况下,lsof
只会列出NAME
(并且只能通过)精确的套接字绑定的名称,无论是相对路径还是绝对路径,并且任何路径工件保持不变:
$ cd /tmp
$ nc -dUl ./././///sock &
[3] 6324
$ ls sock /tmp/sock ./sock
./sock /tmp/sock sock
$ lsof sock /tmp/sock ./sock
[nothing]
$ lsof ./././///sock
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nc 6324 XXX 3u unix 0xffff9f9faab76000 0t0 175260 ./././///sock type=STREAM
请注意,如果是非抽象的unix 域套接字,套接字绑定或连接到的路径仅在内核解析它之前才起作用;它是 [device,inode] 元组,它是套接字绑定或连接到的真实地址:
$ cd /tmp
$ nc -dUl ./././///sock &
[1] 7293
$ mv sock SOCK
$ lsof -aUp $!
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nc 7293 xxx 3u unix 0xffff908d70bb5800 0t0 1137631 ./././///sock type=STREAM
$ lsof ./././///sock
lsof: status error on ./././///sock: No such file or directory
[stupid junk snipped]
$ lsof SOCK
[nothing]
$ nc -U ./././///sock
nc: unix connect failed: No such file or directory
$ nc -U SOCK
[connected ok]
lsof
也无法找到与另一个套接字“连接”(即设置了默认发送地址)的数据报套接字,无法区分@
名称中带有 a 的抽象套接字和名称中带有 NUL 字节的抽象套接字,等等。
以防万一有人想知道,所有需要的信息都可以通过界面获得sock_diag
(UDIAG_SHOW_VFS
,UDIAG_SHOW_PEER
查看linux/unix_udiag.h
标题);只是这lsof
太愚蠢了,无法利用它。
注意:这些示例使用nc
来自 Debian 的软件包netcat-openbsd
,它支持 Unix 套接字。