Install a new shared library and the program that needs it still fails to find it: that is the moment most people meet ldconfig for the first time. This guide covers inspecting the dynamic linker cache, refreshing it after installing shared libraries, and test-scanning a library directory without touching the host. The examples match ldconfig from glibc 2.39, installed here as libc-bin 2.39-0ubuntu8.9. Allow about ten minutes. A normal refresh needs root; inspection does not.
Start by checking which executable your shell will run and which implementation it reports:
$ command -v ldconfig
/usr/sbin/ldconfig
$ ldconfig --version
ldconfig (Ubuntu GLIBC 2.39-0ubuntu8.9) 2.39
The exact copyright and build details can differ. What matters is that the command is present and its version is known. The installed manual page comes from Linux man-pages 6.7 and documents the behaviour used here.
Checkpoint: if command -v finds a wrapper or a non-system copy, stop and inspect it before trusting examples that go on to change the cache.
ldconfig -p prints the libraries recorded in the current cache. It does not rebuild that cache:
$ ldconfig -p | head -n 6
1116 libs found in cache `/etc/ld.so.cache'
libz3.so.4 (libc6,x86-64) => /lib/x86_64-linux-gnu/libz3.so.4
libz3.so (libc6,x86-64) => /lib/x86_64-linux-gnu/libz3.so
libzvbi.so.0 (libc6,x86-64) => /lib/x86_64-linux-gnu/libzvbi.so.0
libzvbi-chains.so.0 (libc6,x86-64) => /lib/x86_64-linux-gnu/libzvbi-chains.so.0
Your count and first entries will differ as packages change. Search for one library by its SONAME or unversioned linker name:
$ ldconfig -p | grep -F -- 'libzstd.so'
libzstd.so.1 (libc6,x86-64) => /lib/x86_64-linux-gnu/libzstd.so.1
libzstd.so (libc6,x86-64) => /lib/x86_64-linux-gnu/libzstd.so
No result just means that name is not in the cache. It does not prove the file does not exist: the directory might not be configured, the cache might be stale, or the file might not have a name ldconfig recognises as a shared object.
When rebuilding, ldconfig scans directories from /etc/ld.so.conf, the trusted library directories, and anything supplied on the command line. On a 64-bit system, multi-architecture library paths matter, so do not assume /lib and /lib64 mean the same thing.
lib*.so*. The dynamic loader itself uses names beginning ld-*.so. A library can sit on disk and still get ignored because its filename does not fit.libexample.so -> libexample.so.1 -> libexample.so.1.12
The middle name is normally the SONAME. The unversioned link is mainly for development linkers, while the versioned SONAME is what programs commonly record as their runtime dependency. Break this chain and a package can look installed while being unusable after an upgrade.Before touching a production library directory, ask ldconfig to scan only that directory, skip the cache output, and skip link updates:
$ sudo ldconfig -nNXv /path/to/library-directory
/path/to/library-directory: (from <cmdline>:0)
-n limits the scan to command-line directories and implies -N.-N prevents rebuilding the cache.-X prevents updating links.-v prints the directories scanned and the links that would otherwise be relevant.The directory has to be readable, and root may be needed if permissions block access. An empty directory printing just its own heading is expected, not an error.
This is a diagnostic, not proof that a library is ABI-compatible with every consumer. Check the actual files separately:
$ find /path/to/library-directory -maxdepth 1 -type f -name 'lib*.so*' -printf '%f\n' | sort
$ readelf -d /path/to/library-directory/libexample.so.1.12 | grep -E 'SONAME|NEEDED'
Only run readelf against a file you trust. An unexpected library directory is a supply-chain and runtime security issue, not merely a cache problem.
Only do this after installing, removing or replacing a shared library through your normal package or deployment process. First check the configuration files that define the search paths:
$ sed -n '1,160p' /etc/ld.so.conf
$ find /etc/ld.so.conf.d -maxdepth 1 -type f -name '*.conf' -print -exec sed -n '1,80p' {} \;
Review those paths for anything unexpected, then rebuild the cache as root:
$ sudo ldconfig
$ ldconfig -p | grep -F -- 'libexample.so'
A successful sudo ldconfig normally produces no output at all. Verify the result with ldconfig -p, then start or test the application that needs the library. If the command fails, keep the error output and resist the urge to rerun it with broader permissions.
Warning: a cache refresh changes /etc/ld.so.cache and may update links in configured library directories. It does not undo a bad library install. If the new library is wrong, use the package manager or deployment rollback that installed it, restore the previous configuration entry, and run sudo ldconfig again. Do not delete the cache as a first response.
The cache is only one input to runtime linking. A program can still fail because its required SONAME is absent, its architecture is wrong, a dependency is missing, or the process is using a different loader path. Inspect the program's declared dependencies without executing it:
$ readelf -d /path/to/program | grep -E 'NEEDED|RPATH|RUNPATH'
$ file /path/to/program /path/to/library-directory/libexample.so.1.12
Compare each NEEDED name against ldconfig -p and the configured directories. Do not "fix" an unresolved dependency by copying a random library into /usr/lib or adding an untrusted directory globally: that can redirect many unrelated programs and turn into a security boundary failure.
Need a temporary per-process search path for a controlled test? Use the application's documented launch mechanism and record it. A global /etc/ld.so.conf.d entry is a persistent system change, so review it, back it up, and schedule its removal if it was only ever meant for a migration.
ldconfig -p before changing anything.-nNXv for a read-only directory scan and know what it does not prove.sudo ldconfig only after reviewing the configured paths.