Package Management – How to Correctly Deal with Lib-Symlinks in Modern Ubuntu Versions

20.0420.10dynamic-linkinglibrariespackage-management

Let's assume that I have some problems with dynamic linking.
I may have some locally built (or manually copied) library which overrides library from APT. The library is not placed to /usr/local/lib, so it is hard to differ it from others.

On Ubuntu 18.04 LTS I can run ldd and then parse its output by something like

export EXE=/usr/bin/mc;

dpkg -S $(ldd $EXE | grep -v "=>" | awk '{print $1}') 2> /tmp/not-from-apt
dpkg -S $(ldd $EXE | grep "=>" | awk '{print $3}') 2>> /tmp/not-from-apt

and then analyze contents of /tmp/not-from-apt file. For non-broken 18.04 LTS system this file will contain only one line:

$ cat /tmp/not-from-apt 
dpkg-query: no path found matching pattern *linux-vdso.so.1*

and it is expected as core library, not came from any package.

But the above method will fail on Ubuntu 20.04 LTS, here the /tmp/not-from-apt file will contain wrong results starting from line 2:

$ cat /tmp/not-from-apt 
dpkg-query: no path found matching pattern *linux-vdso.so.1*
dpkg-query: no path found matching pattern /lib/x86_64-linux-gnu/libgpm.so.2
dpkg-query: no path found matching pattern /lib/x86_64-linux-gnu/libssh2.so.1
dpkg-query: no path found matching pattern /lib/x86_64-linux-gnu/libgmodule-2.0.so.0
dpkg-query: no path found matching pattern /lib/x86_64-linux-gnu/libglib-2.0.so.0
dpkg-query: no path found matching pattern /lib/x86_64-linux-gnu/libgcrypt.so.20

I suppose that this is happened because of symlinks like shown below:

$ ls -al / | grep lib
lrwxrwxrwx   1 root    root       7 Jan 19 04:01 lib -> usr/lib
lrwxrwxrwx   1 root    root       9 Jan 19 04:01 lib32 -> usr/lib32
lrwxrwxrwx   1 root    root       9 Jan 19 04:01 lib64 -> usr/lib64
lrwxrwxrwx   1 root    root      10 Jan 19 04:01 libx32 -> usr/libx32

Really there is another problem here – some packages have /lib* in their filelists, while some have /usr/lib*. So this will add an extra mess.

What should I change in my method for Ubuntu 20.04 LTS and newer to get correct lines in my /tmp/not-from-apt file?

Best Answer

With muru's recommendation we should use realpath command.

But with small note that running realpath on the earliest stage will not work as expected.

So we need to add one extra step to process the output file:

dpkg -S $(realpath $(grep -E "/lib.*" --only-matching /tmp/not-from-apt)) 2> /tmp/not-from-apt-final

And the complete method for 20.04 LTS will look as follows:

export EXE=/usr/bin/mc;

dpkg -S $(ldd $EXE | grep -v "=>" | awk '{print $1}') 2> /tmp/not-from-apt
dpkg -S $(ldd $EXE | grep "=>" | awk '{print $3}') 2>> /tmp/not-from-apt

dpkg -S $(realpath $(grep -E "/lib.*" --only-matching /tmp/not-from-apt)) 2> /tmp/not-from-apt-final

it will produce empty /tmp/not-from-apt-final file when there are no errors.
Also one can always check the contents of /tmp/not-from-apt for extra info.

Related Question