1

只有在使用原始文件时,fuser 才能向您显示。

如果 SYMLINK IS IN USE 调用原始文件,fuser 不会向您显示。这就是问题所在。您不知道符号链接是否未使用并且可以删除。

我已经启动了两个进程(24261 打开原始文件和 24262 打开符号链接):

root@server DEV # ls -l /lib64/libgcc_s-4.4.7-20120601.so.1
-rwxr-xr-x 1 root root 93320 Sep  1  2014 /lib64/libgcc_s-4.4.7-20120601.so.1
root@server DEV # ls -l /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so
lrwxrwxrwx. 1 root root 20 Oct 19  2015 /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so -> /lib64/libgcc_s.so.1
root@server DEV #
root@server DEV # tail -f /lib64/libgcc_s.so.1 &
[1] 24261
root@server DEV #
root@server DEV # cd /usr/lib/gcc/x86_64-redhat-linux/4.4.4
root@server DEV # tail -f libgcc_s.so &
[2] 24262
root@server DEV #
root@server DEV # ps -ef | grep tail
root     24261  3265  0 13:39 pts/1    00:00:00 tail -f /lib64/libgcc_s.so.1
root     24262  3265  0 13:39 pts/1    00:00:00 tail -f libgcc_s.so
root     24492  3265  0 13:40 pts/1    00:00:00 grep tail
root@server DEV #

在这两种情况下,fuser 都会告诉符号链接和原始文件正在使用中(每个命令有两个进程):

root@server DEV # fuser /lib64/libgcc_s.so.1
/lib64/libgcc_s.so.1: 24261 24262
root@server DEV # fuser /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so
/usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so: 24261 24262
root@server DEV #

但是我们知道第一个进程没有使用符号链接。它甚至可以被删除,不会影响第一个过程。

假设如果包未使用,我想删除“gcc”包。

原始文件来自“libgcc”包。

root@server DEV # rpm -qf /lib64/libgcc_s.so.1
libgcc-4.4.7-11.el6.x86_64

符号链接来自“gcc”包:

root@server DEV # rpm -qf /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so
gcc-4.4.7-11.el6.x86_64

如果我要删除只包含符号链接的“gcc”包,我会影响第二个进程!如何查看符号链接是否未使用?

就我而言,“ps -ef”表明我使用了命令:

root     24262  3265  0 13:39 pts/1    00:00:00 tail -f libgcc_s.so

所以 ps 甚至不能告诉你使用了符号链接。

有 Linux 大师吗?

编辑:有部分解决方案检查 cwd - 当前工作目录:

root@server DEV # ls -l /proc/24262/cwd
lrwxrwxrwx 1 root root 0 Jun 20 13:57 /proc/24262/cwd -> /usr/lib/gcc/x86_64-redhat-linux/4.4.4
root@server DEV #

所以从这里你可以看到路径“/usr/lib/gcc/x86_64-redhat-linux/4.4.4”,你可以从 ps 获取文件名。

如果您这样做,这将不起作用:

root@server DEV # cd /root
root@server DEV # cat script.sh
/usr/bin/tail -f /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so
root@server DEV #
root@server DEV # nohup ./script.sh &
[2] 26713
root@server DEV #
root@server DEV # ls -l /proc/26713/cwd
lrwxrwxrwx 1 root root 0 Jun 20 14:32 /proc/26713/cwd -> /root

它显示 /root 的 cwd,但符号链接在脚本/程序内。那么你需要检查 /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so 的 ps chill 进程。

root@server DEV # ps -ef | grep 26713
root     26713  3265  0 14:32 pts/1    00:00:00 /bin/sh ./script.sh
root     26714 26713  0 14:32 pts/1    00:00:00 /usr/bin/tail -f /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so
root     26780  3265  0 14:38 pts/1    00:00:00 grep 26713
root@server DEV #

当您想要自动删除包时(如果包未在使用中),这非常令人困惑。

如果有人能看到更简单的方法,那就太好了。此外,如果有人可以确认在使用检测中使用 cwd 和 ps 子进程进行符号链接的准确性。

如果 script.sh 是二进制文件会发生什么?我还能在“ps”或 cwd 中看到完整的符号链接路径吗?

4

4 回答 4

2

符号链接不是普通文件:它们不能open()普通文件或目录一样打开。Symlink 实际上只是一个常量 string,在路径解析期间会在内部自动解释。

因为符号链接在fuser. 当您为符号链接调用fuser时,它实际上显示了有关链接指向的文件的信息。

于 2016-06-20T16:25:12.583 回答
1

如果“使用中”是指“一个或多个程序正在使用该链接作为文件的路径名”,那么就无法判断。昨天可以用,明天就可以用了。Unix 的设计是这样的,除非您专门使用为特定目的设计的工具,否则符号链接看起来就像它指向的文件。喜欢fuserlsof将直接通过链接的程序甚至不会告诉您这是一个链接。

如果“使用中”是指“指向有效文件”,那么有多种方法可以判断。最简单的存在ls -L

$ ls -l foo
/bin/ls: cannot access foo: No such file or directory
$ ls -l g
lrwxrwxrwx 1 hymie users 3 2016-06-20 10:09 g -> foo
$ ls -lL g
/bin/ls: cannot access g: No such file or directory
于 2016-06-20T14:10:44.087 回答
0

不幸的是,Linux 内核被设计为在启动阶段从符号链接分配原始文件。因此,当进程运行时,无法检查文件是直接调用还是通过符号链接调用。

您所能做的就是检查当前工作目录ls -l /proc/<process_id>/cwd、命令行参数strings /proc/<process_id>/cmdline、启动进程的用户,ps -ef | grep <process_id>然后您可以检查用户启动脚本,并且$PATH可以ldd向您显示从特定库调用的库。如果您想重新启动该过程以查看调用的符号链接strace是否是您的朋友。

于 2016-06-21T10:17:20.303 回答
0

这个问题的前提(用fuser/标识未使用的包lsof)从根本上是有缺陷的:

并非您的系统需要正常工作的每个文件都会在任何随机时间被打开的文件描述符引用。

例如,如果您将其删除/bin/systemctl(因为诸如/sbin/shutdown符号链接之类的东西),您将度过一段糟糕的时光,但 lsof 没有显示任何使用它的内容。

很容易想出更多的例子,比如/bin/grep在我的系统上。它在 shell 脚本中随处可见,但我碰巧没有任何长期运行的实例。

于 2016-07-02T00:07:58.703 回答