用于创建指向共享库的符号链接的 Bash 脚本

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/462100/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 17:54:30  来源:igfitidea点击:

Bash script to create symbolic links to shared libraries

linuxbashscriptingjava-native-interfaceshared-libraries

提问by Fernando Miguélez

I think this question is rather easy for you shell scripting monsters.

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

I am looking for the most elegant and shortest way to create symbolic links to shared libraries for Unix by means of a bash shell script.

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

What I need is starting out with a list of shared library files such as "libmythings.so.1.1, libotherthings.so.5.11", get the symbolic links created such as:

我需要的是从共享库文件列表开始,例如“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

The library files are inside a directory which contains other files such as other shell scripts.

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

EDIT: Well, "ldconfig -nN ." could work OK, but I also need the link without the major number of the library appended after ".so", at least one of the libraries, since one or more libraries are the entry points of JNI calls from Java, so when a library is instanced by means of System.loadlibrary("libraryname") it expects a library called "libraryname.so", not "libraryname.so.X".

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

The solution with just ldconfig -nN could work if there were a workaround for the Java part.

如果 Java 部分有解决方法,那么仅使用 ldconfig -nN 的解决方案就可以工作。

回答by Kent Fredric

I believe ldconfigis the standard tool that does this.

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

I recall somewhere it can generate symlinks based on internal version info, but can't find the source right now.

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

EDITYes, if you run

编辑是的,如果你跑

ldconfig -v 

You'll see it generating all the links based on library internals.

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

ldconfig /path/to/dir 

Will only create links for files in that dir

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

A note though, I played with it and it doesn't seem to consistently create .so$, just .so.{major}

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

I'm not sure how its internals work, but I do know:

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

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)

So what determines how this works is a mystery to me

所以是什么决定了它是如何工作的对我来说是个谜

EditUpon Further Discetion, .la files have no influence on behaviour.

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

The "SO" name field indicates what the symlink will be called.

“SO”名称字段指示符号链接将被称为什么。

And there will only be one.

而且只会有一个。

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

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

This is after hacking the code and replacing the ".1" with spaces.

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

ldconfig generated "libmagic.so " ( yes, spaces included )

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

回答by Jonathan Leffler

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

I've cheated - all the links go to the base library (libmythings.so.1.1); if you really want to chain, then you need:

我作弊了 - 所有链接都指向基础库(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           

Beware - untested code.

当心 - 未经测试的代码。



Hubris precedes nemesis.

傲慢先于克星。

Comment arrived that the code above doesn't work - and the comment is correct. A fixed version with test in situ is:

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

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]*\)$//p')
          [ -n "$extn" ]
    do
        shortlib=$(basename $shortlib $extn)
        echo ln -s $baselib $shortlib
    done
done

The change is in the sedcommand. This version doesn't print anything by default (-n), matches only lines ending with a dot followed by digits, and then deletes everything except that suffix, and prints what remains for assignment to extn. As amended, the script generates the output below. Remove the echo to get it to execute the link commands.

更改在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

The script illustrates an interesting and often overlooked point about shell scripts: the sequence of operations in the condition block of a while need not be a single command. The status of the line with the edit operation doesn't affect whether the test as a whole succeeds; the exit status of the last command, the '[ -n "$extn" ]', controls whether the loop continues.

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

回答by user1016736

Derived from the script from Jonathan Leffler (I've added this as a script called 'liblinks' in my ~/bin )

源自 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]*\)$//p')
          [ -n "$extn" ]
    do
        shortlib=$(basename $shortlib $extn)
        sudo ln -fs $basename $shortlib
        basename=$shortlib
    done

   done