【问题标题】:Bash script to create symbolic links to shared libraries用于创建指向共享库的符号链接的 Bash 脚本
【发布时间】:2010-10-02 12:05:18
【问题描述】:

我认为这个问题对你们这些 shell 脚本怪物来说是相当容易的。

我正在寻找通过 bash shell 脚本创建指向 Unix 共享库的符号链接的最优雅和最短的方法。

我需要的是从共享库文件列表开始,例如“libmythings.so.1.1,libotherthings.so.5.11”,获取创建的符号链接,例如:

libmythings.so -> libmythings.so.1 -> libmythings.so.1.1
libotherthings.so -> libotherthings.so.5 -> libotherthings.so.5.11

库文件位于包含其他文件(例如其他 shell 脚本)的目录中。

编辑:嗯,“ldconfig -nN”。可以正常工作,但我还需要没有在“.so”之后附加库的主要编号的链接,至少是其中一个库,因为一个或多个库是来自 Java 的 JNI 调用的入口点,所以当一个库通过 System.loadlibrary("libraryname") 实例化,它需要一个名为“libraryname.so”的库,而不是“libraryname.so.X”。

如果有针对 Java 部分的解决方法,仅使用 ldconfig -nN 的解决方案可能会起作用。

【问题讨论】:

    标签: linux bash scripting java-native-interface shared-libraries


    【解决方案1】:

    我相信ldconfig 是执行此操作的标准工具。

    我记得它可以根据内部版本信息生成符号链接,但现在找不到源。

    编辑是的,如果你运行

    ldconfig -v 
    

    您会看到它根据库内部结构生成所有链接。

    ldconfig /path/to/dir 
    

    只会为该目录中的文件创建链接

    不过,我玩过它,但它似乎并没有始终如一地创建 .so$,只是 .so.{major}

    我不确定它的内部是如何工作的,但我知道:

    lib # rm libmagic.so 库#rm libmagic.so.1 库#ldconfig lib # 文件 libmagic.so.1 libmagic.so.1:指向“libmagic.so.1.0.0”的符号链接 lib # 文件 libmagic.so libmagic.so:无法打开“libmagic.so”(没有这样的文件或目录)

    那么是什么决定了它的工作原理对我来说是个谜

    编辑 进一步谨慎后,.la 文件对行为没有影响。

    “SO”名称字段指示符号链接将被调用的内容。

    而且只有一个。

    0x000000000000000e (SONAME) 库 soname: [libmagix.so]

    这是在修改代码并将“.1”替换为空格之后。

    ldconfig 生成“libmagic.so”(是的,包括空格)

    【讨论】:

    • "ldconfig -nN 。"只适用于当前目录,但它只能创建库的主要版本(libmylib.1 -> libmylib.1.10)。
    【解决方案2】:
    for baselib in "$@"
    do
         shortlib=$baselib
         while extn=$(echo $shortlib | sed 's/\.[0-9][0-9]*$//')
               [ -n "$extn" ]
         do
             shortlib=$(basename $shortlib $extn)
             ln -s $baselib $shortlib
         done
    done
    

    我作弊了——所有链接都指向基础库 (libmythings.so.1.1);如果你真的想链,那么你需要:

    for baselib in "$@"
    do
         shortlib=$baselib
         while extn=$(echo $shortlib | sed 's/\.[0-9][0-9]*$//')
               [ -n "$extn" ]
         do
             shorterlib=$(basename $shortlib $extn)
             ln -s $shortlib $shorterlib
             shortlib=$shorterlib
         done
    done           
    

    小心 - 未经测试的代码。


    傲慢先于克星。

    评论到达,上面的代码不起作用 - 并且评论是正确的。原位测试的固定版本是:

    set -- libname.so.5.1.1
    
    for baselib in "$@"
    do
        shortlib=$baselib
        while extn=$(echo $shortlib | sed -n '/\.[0-9][0-9]*$/s/.*\(\.[0-9][0-9]*\)$/\1/p')
              [ -n "$extn" ]
        do
            shortlib=$(basename $shortlib $extn)
            echo ln -s $baselib $shortlib
        done
    done
    

    更改在sed 命令中。这个版本默认不打印任何东西(-n),只匹配以点结尾的行,然后删除除后缀之外的所有内容,并打印剩余的内容以分配给 extn。修改后,脚本生成以下输出。去掉 echo 让它执行链接命令。

    ln -s libname.so.5.1.1 libname.so.5.1
    ln -s libname.so.5.1.1 libname.so.5
    ln -s libname.so.5.1.1 libname.so
    

    该脚本说明了有关 shell 脚本的一个有趣且经常被忽视的点:while 条件块中的操作序列不必是单个命令。编辑操作所在行的状态不影响整体测试是否成功;最后一个命令“[ -n "$extn" ]”的退出状态控制循环是否继续。

    【讨论】:

    • 你得到了正确的答案,虽然我已经通过“cut”命令自己完成了。谢谢。
    【解决方案3】:

    源自 Jonathan Leffler 的脚本(我已将其添加为我的 ~/bin 中名为 'liblinks' 的脚本)

    #!/bin/bash
    # liblinks - generate symbolic links 
    # given libx.so.0.0.0 this would generate links for libx.so.0.0, libx.so.0, libx.so
    #
    
    # By adding sudo to the ls command, we get permission to do the linking (or get an empty list)
    LIBFILES=`sudo ls lib*.so.*`
    for FILE in $LIBFILES;
       do
       echo $FILE
        shortlib=$FILE
        basename=$FILE
        while extn=$(echo $shortlib | sed -n '/\.[0-9][0-9]*$/s/.*\(\.[0-9][0-9]*\)$/\1/p')
              [ -n "$extn" ]
        do
            shortlib=$(basename $shortlib $extn)
            sudo ln -fs $basename $shortlib
            basename=$shortlib
        done
    
       done
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-18
      • 2016-10-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多