1

fuser can show you ONLY if original file is in use.

fuser DOESN'T SHOW YOU IF SYMLINK IS IN USE which calls original file. That's the issue. You don't know if symlink unused and can be removed.

I have started two processes (24261 opened original file and 24262 opened symlink) :

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 #

In both cases fuser tells that symlink and original file is in use (there are two processes for each command):

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 #

But we know that symlink was not used for the first process. It can be even removed and will not affect first process.

Let's say I want to remove 'gcc' package if the package is not in use.

Original file comes from 'libgcc' package.

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

Symlink comes from 'gcc' package:

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

If I will remove 'gcc' package which contains only symlink, I will affect second process! How I can see if symlink is unused?

In my case 'ps -ef' shows that I used command:

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

So ps cannot even tell you that symlink was used.

Any Linux guru?

EDITED: There is partial solution checking cwd - current working directory:

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 #

So from here you see the path "/usr/lib/gcc/x86_64-redhat-linux/4.4.4" and you can get file name from ps.

This doesn't work if you do:

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

It shows cwd for /root, but symlink is inside the script/program. So then you need to check ps chill process for /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so.

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 #

This is very confusing when you want to automate package removal (if the package is not in use).

It will be great if someone can see simpler way of this. Also if someone can confirm the accuracy of using cwd and ps child processes for symlink in use detection.

What will happen if script.sh would be binary file? Will I still able to see full symlink path in 'ps' or cwd?

laimison
  • 1,409
  • 3
  • 17
  • 39
  • Why do you need to remove unused symlinks? – Thilo Jun 20 '16 at 13:29
  • I need to remove unused compilers (e.g. gcc). This is for security purposes. – laimison Jun 20 '16 at 13:46
  • 1
    What is the relationship between "unused compilers" and symlinks? – hymie Jun 20 '16 at 14:07
  • These are in the same package. For example:`root@server DEV # rpm -ql gcc | grep -e '/usr/bin/gcc' -e '/usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so' /usr/bin/gcc /usr/lib/gcc/x86_64-redhat-linux/4.4.4/libgcc_s.so` – laimison Jun 20 '16 at 14:30
  • So now I'm confused. You're concerned that, if you remove the gcc package, then nobody will be able to use it? – hymie Jun 20 '16 at 14:42
  • I'm looking for good check if package is in use before the removal. So then I can remove unused package (and symlinks). If the package is in use then I do not want to remove it, the process owner should be contacted for further actions. – laimison Jun 20 '16 at 15:04

4 Answers4

2

Symlinks are not usual files: they cannot be opened with open() like regular files or directories. Symlink actually is just a constant string, which is automatically interpreted internally during path resolution.

Because of that symlinks are not "used" in the sence of utilities like fuser. When you call fuser for symlink, it actually shows info about file pointed by the link.

Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
1

If by "in use" you mean "one or more programs is using the link as its path name for the file", then there is no way to tell. It could have been used yesterday, and it might be used tomorrow. Unix is designed so that, unless you are specifically using tools designed for that specific purpose, a symlink looks just like the file it points to. Programs like fuser or lsof will just go right through the links without even telling you it's a link.

If by "in use" you mean "points to a valid file", then there are ways to tell. The simplest being 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
hymie
  • 1,982
  • 1
  • 13
  • 18
  • This is the problem that Unix/Linux cannot easily tell you about symlink if it's is in use right now. If the process was running yesterday or short lived, or etc. there is a solution 'auditd' tool. – laimison Jun 20 '16 at 14:37
0

Unfortunately, Linux kernel is designed to assign original file from the symlink in the start up phase. So when the process is running there is no possibility to check if file called directly or through symlink.

All you can do is to check what was current working directory ls -l /proc/<process_id>/cwd, command line arguments strings /proc/<process_id>/cmdline, what user started the process ps -ef | grep <process_id> then you can check user startup scripts and $PATH, ldd can show you which libraries are called from particular library. If you want to restart the process to see if symlink called then strace is your friend.

laimison
  • 1,409
  • 3
  • 17
  • 39
0

The premise of this question (identifying unused packages with fuser / lsof) is fundamentally flawed:

Not every file your system needs to work properly will referenced by an open file descriptor at any random time.

For example, you would have a bad time if you removed /bin/systemctl (since things like /sbin/shutdown are symlinks to it), but lsof shows nothing using it.

It's easy to come up with many more examples, like /bin/grep on my system. It's used all over the place in shell scripts, but I don't happen to have any long-running instances of it.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847