代码之家  ›  专栏  ›  技术社区  ›  Community wiki

Bash脚本创建到共享库的符号链接

  •  7
  • Community wiki  · 技术社区  · 2 年前

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

    我正在寻找一种最优雅、最短的方法,通过bashshell脚本为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的解决方案就可以工作。

    3 回复  |  直到 17 年前
        1
  •  15
  •   Kent Fredric    17 年前

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

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

    编辑 是的,如果你跑步

    ldconfig -v 
    

    您将看到它基于库内部生成所有链接。

    ldconfig /path/to/dir 
    

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

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

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

    lib # rm libmagic.so
    lib # rm libmagic.so.1
    lib # ldconfig 
    lib # file libmagic.so.1   
    libmagic.so.1: symbolic link to `libmagic.so.1.0.0'
    lib # file libmagic.so 
    libmagic.so: cannot open `libmagic.so' (No such file or directory)
    

    所以,是什么决定了这是如何运作的,对我来说是个谜

    编辑 在进一步丢弃后,.la文件对行为没有影响。

    “SO”名称字段指示符号链接的名称。

    而且只有一个。

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

    这是在破解代码并用空格替换“.1”之后。

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

        2
  •  7
  •   Jonathan Leffler    17 年前
    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脚本中一个有趣且经常被忽视的点:一段时间内条件块中的操作序列不需要是一个命令。带有编辑操作的行的状态不影响整个测试是否成功;最后一个命令的退出状态 [ -n "$extn" ] ',控制循环是否继续。

        3
  •  5
  •   user1016736    14 年前

    源自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