简体   繁体   中英

How can I find the full file path given a library name like libfoo.so.1?

Without implementing a linker or using ldd , how can I find the full path to a library? Is there a standard library available for that on Linux? (POSIX maybe?)

Using ldd and grep on a file that is knowingly using libGL.so.1 , it looks like:

$ ldd /usr/bin/glxinfo | grep libGL
libGL.so.1 => /usr/lib/libGL.so.1 (0x00007f34ff796000)

Given a library name like libGL.so.1 , how can I find the full path /usr/lib/libGL.so.1 ? . Preferably accepting an option for finding 32-bit and 64-bit libraries. If no library does that, does a program exist to do this? Something like find-library-path libGL.so.1 . The locate libGL.so.1 command does not count.

I don't want to actually load the library using dlopen or something if it executes code from that library.

Use ldconfig which is the tool that manages link space.

The -p flag lets you browse all available linkable libraries.

扩展 Honky Tonk 的回答,命令echo "$(ldconfig -p | grep libGL.so.1 | tr ' ' '\\n' | grep /)"会给你单独的路径。

如果您不介意实际加载库并使用一些非标准但广泛可用的函数, dladdr对库中的任何符号调用dladdr将返回包含加载的完整路径名的信息。

For systems with GNU libc and Python the following is the closest I found. It uses LD_DEBUG (described in the man page of ld.so(8) ).

LD_DEBUG=libs python3 -c "import ctypes; ctypes.CDLL('libssl.so.1.0.0')" 2>&1 | \
    grep -A 1000 "initialize program: python" | grep -A 3 "find library"

The output (for libssl.so.1.0.0 ) is the following:

 15370: find library=libssl.so.1.0.0 [0]; searching
 15370:  search cache=/etc/ld.so.cache
 15370:   trying file=/lib/x86_64-linux-gnu/libssl.so.1.0.0
 15370: 
 15370: find library=libcrypto.so.1.0.0 [0]; searching
 15370:  search cache=/etc/ld.so.cache
 15370:   trying file=/lib/x86_64-linux-gnu/libcrypto.so.1.0.0
 15370: 

I implemented such a script here :

#!/usr/bin/env python3

"""
Like `type` but for libs.
"""

import sys
import os
from argparse import ArgumentParser
from glob import glob


def parse_ld_conf_file(fn):
    paths = []
    for l in open(fn).read().splitlines():
        l = l.strip()
        if not l:
            continue
        if l.startswith("#"):
            continue
        if l.startswith("include "):
            for sub_fn in glob(l[len("include "):]):
                paths.extend(parse_ld_conf_file(sub_fn))
            continue
        paths.append(l)
    return paths


def get_ld_paths():
    # To be very correct, see man-page of ld.so.
    # And here: http://unix.stackexchange.com/questions/354295/what-is-the-default-value-of-ld-library-path/354296
    # Short version, not specific to an executable, in this order:
    # - LD_LIBRARY_PATH
    # - /etc/ld.so.cache (instead we will parse /etc/ld.so.conf)
    # - /lib, /usr/lib (or maybe /lib64, /usr/lib64)
    paths = []
    if "LD_LIBRARY_PATH" in os.environ:
        paths.extend(os.environ["LD_LIBRARY_PATH"].split(":"))
    paths.extend(parse_ld_conf_file("/etc/ld.so.conf"))
    paths.extend(["/lib", "/usr/lib", "/lib64", "/usr/lib64"])
    return paths


def main():
    arg_parser = ArgumentParser()
    arg_parser.add_argument("lib")
    args = arg_parser.parse_args()

    paths = get_ld_paths()
    for p in paths:
        fn = "%s/%s" % (p, args.lib)
        if os.path.exists(fn):
            print(fn)
            return

    print("Did not found %r in %r." % (args.lib, paths), file=sys.stderr)
    sys.exit(1)


if __name__ == "__main__":
    main()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM