Programs on Linux often require external libraries to run correctly. These libraries are either loaded dynamically during runtime or built directly into the program. By using shared libraries, programs can reduce size and reuse common code. Typically, shared libraries are stored in the /lib or /usr/lib directories.
A program compiled on one version of Linux may not work on another if the required libraries are missing or incompatible. This can lead to errors, especially when the program tries to load a shared library that is absent. Missing libraries or incorrect versions can prevent the program from starting, often resulting in an error like cannot open shared object file.
$ sudo dpkg sudo: error while loading shared libraries: libpthread.so.0: cannot open shared object file: No such file or directory
To fix these issues, you can inspect the program's shared library dependencies. Linux provides tools like ldd to list dynamic libraries required by a program. These tools help identify the exact dependencies so that missing libraries can be installed or updated as needed.
Steps to check library dependencies in Linux:
- Open the terminal application.
- Determine the absolute path of the program you want to inspect.
$ which bash /usr/bin/bash
- Display the shared object dependencies of the program.
$ ldd /usr/bin/bash linux-vdso.so.1 (0x00007ffdd2749000) libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fcecb9b6100) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fcecb9b0000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcecb7c5000) /lib64/ld-linux-x86-64.so.2 (0x00007fcecbb21000)
The ldd command shows all shared libraries required by a program. The path returned points to where each library is located on the system.
- Run ldd in verbose mode to view additional information.
$ ldd --verbose /usr/bin/bash linux-vdso.so.1 (0x00007ffce299c000) libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f6fb24dd000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f6fb24d6100) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f6fb22ec000) /lib64/ld-linux-x86-64.so.2 (0x00007f6fb2648000) Version information: /usr/bin/bash: libdl.so.2 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libdl.so.2 libtinfo.so.6 (NCURSES6_TINFO_5.0.19991023) => /lib/x86_64-linux-gnu/libtinfo.so.6 libc.so.6 (GLIBC_2.11) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.8) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.15) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/libtinfo.so.6: libc.so.6 (GLIBC_2.3) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.14) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.16) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.3.4) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/libdl.so.2: ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2 libc.so.6 (GLIBC_PRIVATE) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.4) => /lib/x86_64-linux-gnu/libc.so.6 libc.so.6 (GLIBC_2.2.5) => /lib/x86_64-linux-gnu/libc.so.6 /lib/x86_64-linux-gnu/libc.so.6: ld-linux-x86-64.so.2 (GLIBC_2.3) => /lib64/ld-linux-x86-64.so.2 ld-linux-x86-64.so.2 (GLIBC_PRIVATE) => /lib64/ld-linux-x86-64.so.2
More options for ldd:
$ ldd --help Usage: ldd [OPTION]... FILE... --help print this help and exit --version print version information and exit -d, --data-relocs process data relocations -r, --function-relocs process data and function relocations -u, --unused print unused direct dependencies -v, --verbose print all information For bug reporting instructions, please see: <https://bugs.launchpad.net/ubuntu/+source/glibc/+bugs>.
- Use readelf to check dynamic library dependencies of a program.
$ readelf --dynamic /usr/bin/bash | grep NEEDED 0x0000000000000001 (NEEDED) Shared library: [libtinfo.so.6] 0x0000000000000001 (NEEDED) Shared library: [libdl.so.2] 0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
- Inspect libraries required by a running process using the proc filesystem.
$ awk '/\.so/{print $6}' /proc/$(pgrep bash | head -n1)/maps | sort -u /usr/lib/x86_64-linux-gnu/ld-2.29.so /usr/lib/x86_64-linux-gnu/libc-2.29.so /usr/lib/x86_64-linux-gnu/libdl-2.29.so /usr/lib/x86_64-linux-gnu/libnss_files-2.29.so /usr/lib/x86_64-linux-gnu/libtinfo.so.6.1
- List memory-mapped shared libraries of a running process using lsof.
$ lsof -p $(pgrep bash | head -n1) | grep mem\ bash 4470 user mem REG 8,1 51672 404577 /usr/lib/x86_64-linux-gnu/libnss_files-2.29.so bash 4470 user mem REG 8,1 14529344 401393 /usr/lib/locale/locale-archive bash 4470 user mem REG 8,1 2000480 403822 /usr/lib/x86_64-linux-gnu/libc-2.29.so bash 4470 user mem REG 8,1 18656 403961 /usr/lib/x86_64-linux-gnu/libdl-2.29.so bash 4470 user mem REG 8,1 183528 404929 /usr/lib/x86_64-linux-gnu/libtinfo.so.6.1 bash 4470 user mem REG 8,1 26402 789841 /usr/lib/x86_64-linux-gnu/gconv/gconv-modules.cache bash 4470 user mem REG 8,1 179032 403610 /usr/lib/x86_64-linux-gnu/ld-2.29.so
pgrep bash | head -n1 fetches the process ID of the first bash process running.
- Use pmap to check the memory maps of a running process and list shared libraries.
$ pmap $(pgrep bash | head -n1) | grep \.so | awk '{ print $4 }' | sort -u ld-2.29.so libc-2.29.so libdl-2.29.so libnss_files-2.29.so libtinfo.so.6.1
Mohd Shakir Zakaria is an experienced cloud architect with a strong development and open-source advocacy background. He boasts multiple certifications in AWS, Red Hat, VMware, ITIL, and Linux, underscoring his expertise in cloud architecture and system administration.
Comment anonymously. Login not required.