0

我正在连接ssh到另一台机器以执行 bash 脚本,其问题部分如下:

fkeypar "ex1.fef[1]" TSTARTI         #### fkeypar is an external command to get some values to assign to the subsequent variables
t0i="$(expr $(pget fkeypar value) - 11544)"                                          
fkeypar "ex1lc.fits[2]" TELAPSE
lengthini=`pget fkeypar value`
fkeypar "ex7lc.fits[2]" TSTOP
lengthfin=`pget fkeypar value`
fkeypar "ex1lc.fits[2]" TSTART      
ijd=`pget fkeypar value`

i=$(echo "($ijd - $t0i) / $period + 1" | bc -l | sed 's/\..*//')
ifin=$(echo "($lengthfin - $ijd)/$period + 1" | bc -l | sed 's/\..*//')
echo "($ijd - $t0i) / $period + 1" | bc

for ((n=$i; n<=$ifin; n++))
do
   ...

这将返回以下错误:

bc: symbol lookup error: /science/heasoft-6.14/x86_64-unknown-linux-gnu-libc2.9/lib/libreadline.so.6: undefined symbol: PC
bc: symbol lookup error: /science/heasoft-6.14/x86_64-unknown-linux-gnu-libc2.9/lib/libreadline.so.6: undefined symbol: PC
bc: symbol lookup error: /science/heasoft-6.14/x86_64-unknown-linux-gnu-libc2.9/lib/libreadline.so.6: undefined symbol: PC
./script: line 39: ((: n=: syntax error: operand expected (error token is "=")

谷歌搜索了很多,我发现我与这些“错误”非常相关: https ://science.nrao.edu/forums/viewtopic.php?f=44&t=75

https://bugzilla.redhat.com/show_bug.cgi?id=162023

https://dba.stackexchange.com/questions/31143/libreadline-so-6

我不知道如何解决它,而不尝试随机的事情。任何帮助都非常感谢。

编辑:我忘了提到,在我的许多试验中,ssh-ing 很多次,我设法以某种方式没有得到错误并运行脚本,其语法与问题中报告的相同。那一刻,我以为是语法问题,但是在随后的 ssh-ings 中又出现了错误。

EDIT2:我加载的版本无关紧要heasoft,该版本总是出现错误heasoft-6.14。我认为这与可能的修复有关。

4

2 回答 2

2

Most of this is a problem we can't help with -- someone with administrative rights to recompile bc (or, better, someone who knows why you're not doing the sane thing and using an OS-vendor-provided version) would need to fix it. (This may be as simple as renaming the bc under /science/heasoft-6.14 out of the way, and allowing a vendor-provided implementation in the PATH to be used instead).

That said, if you're only doing integer math, there's no reason for this script to use bc at all:

i=$(( (idj - t01) / period + 1 ))
ifin=$(( ( lengthfin - ijd ) / period + 1 ))
echo "$(( ( ijd - t01 ) / period + 1 ))"

The error you have on line 39 is a consequence of these bugs in bc -- the script expects i to contain a number, but it's an empty string, so n=$i can't evaluate "$i" as a number, so it fails. In a math context (which is what the double parenthesis create), i evaluates as 0 if the variable is undefined, but $i causes an error in that same scenario; which of these to use depends on your desired behavior. If you want an error when a variable is undefined, use $varname inside of (( )); if you want the script to continue with a value of 0, use bare varname.

于 2014-06-26T07:01:34.193 回答
1

我不知道如何解决它,而不尝试随机的事情。任何帮助都非常感谢。

在你的平台上构建 Readline 的方法被打破了。以下是技术细节......共享对象缺少符号,这没关系:

$ ldd -r -d /usr/local/lib/libreadline.so
        linux-vdso.so.1 (0x00007ffea672a000)
        libc.so.6 => /lib64/libc.so.6 (0x00007fec922eb000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fec92521000)
undefined symbol: UP    (/usr/local/lib/libreadline.so)
undefined symbol: PC    (/usr/local/lib/libreadline.so)
undefined symbol: BC    (/usr/local/lib/libreadline.so)
undefined symbol: tputs (/usr/local/lib/libreadline.so)
undefined symbol: tgoto (/usr/local/lib/libreadline.so)
undefined symbol: tgetflag      (/usr/local/lib/libreadline.so)
undefined symbol: tgetent       (/usr/local/lib/libreadline.so)
undefined symbol: tgetnum       (/usr/local/lib/libreadline.so)
undefined symbol: tgetstr       (/usr/local/lib/libreadline.so)

实际上,我认为构建应该由于缺少符号而失败。但是维护者不这么认为,他更愿意将他的痛苦和痛苦传播给他图书馆的用户。

缺少的符号是 Ncurses 和 Terminfo 的一部分,但缺少链接库。那不行。链接库应该类似于libtinfo.soorlibtinfow.so但它缺少:

$ ldd /usr/local/lib/libreadline.so
        linux-vdso.so.1 (0x00007ffd535cb000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3a5183c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3a520b5000)

这里是和朋友所在的位置UPPC

$ nm -D /usr/local/lib/libtinfow.so | grep -E 'UP|PC'
000000000023797e B PC
0000000000237968 B UP

您应该能够在 Readline 配置期间添加-ltinfo或添加-ltinfow到您的LIBS/LDLIBS中,但这不起作用。添加-ltinfo或被-ltinfow忽略。

实践中的修复是修补 Readline makefile,然后从源代码构建 Ncurses 和 Readline。

这是 Readline 补丁的样子。该补丁是使用以下内容创建的diff -u

--- shlib/Makefile.in
+++ shlib/Makefile.in
@@ -174,11 +174,11 @@
 
 $(SHARED_READLINE):    $(SHARED_OBJ)
    $(RM) $@
-   $(SHOBJ_LD) ${SHOBJ_LDFLAGS} ${SHLIB_XLDFLAGS} -o $@ $(SHARED_OBJ) $(SHLIB_LIBS)
+   $(SHOBJ_LD) ${SHOBJ_LDFLAGS} ${SHLIB_XLDFLAGS} -o $@ $(SHARED_OBJ) $(SHLIB_LIBS) -ltinfo
 
 $(SHARED_HISTORY): $(SHARED_HISTOBJ) xmalloc.so xfree.so
    $(RM) $@
-   $(SHOBJ_LD) ${SHOBJ_LDFLAGS} ${SHLIB_XLDFLAGS} -o $@ $(SHARED_HISTOBJ) xmalloc.so xfree.so $(SHLIB_LIBS)
+   $(SHOBJ_LD) ${SHOBJ_LDFLAGS} ${SHLIB_XLDFLAGS} -o $@ $(SHARED_HISTOBJ) xmalloc.so xfree.so $(SHLIB_LIBS) -ltinfo
 
 # Since tilde.c is shared between readline and bash, make sure we compile 
 # it with the right flags when it's built as part of readline

修复 makefile 并构建 Ncurses 和 Readline 后,您的链接库将包括libtinfo.so. 狗屎将不再被打破。通知libtinfo.so链接如下。

$ ldd /usr/local/lib/libreadline.so
        linux-vdso.so.1 (0x00007ffd535cb000)
        libtinfow.so.6 => /usr/local/lib/libtinfow.so.6 (0x00007f3a51c2d000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3a5183c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3a520b5000)

现在,正确配置 Ncurses 可能会很棘手。那是因为所有库都有一个非宽版本和宽版本。Ncurses 中有 6 个类似的东西:

$ ls /usr/local/lib/lib*w\.so*
/usr/local/lib/libformw.so         /usr/local/lib/libncursesw.so.6
/usr/local/lib/libformw.so.6       /usr/local/lib/libncurses++w.so.6.1
/usr/local/lib/libformw.so.6.1     /usr/local/lib/libncursesw.so.6.1
/usr/local/lib/libmenuw.so         /usr/local/lib/libpanelw.so
/usr/local/lib/libmenuw.so.6       /usr/local/lib/libpanelw.so.6
/usr/local/lib/libmenuw.so.6.1     /usr/local/lib/libpanelw.so.6.1
/usr/local/lib/libncurses++w.so    /usr/local/lib/libtinfow.so
/usr/local/lib/libncursesw.so      /usr/local/lib/libtinfow.so.6
/usr/local/lib/libncurses++w.so.6  /usr/local/lib/libtinfow.so.6.1

我使用配置选项构建了 Ncurses的广泛--enable-widec版本。--enable-widec描述为

此开关导致构建宽字符库(例如 libncursesw.so.6.2)而不是普通库(例如 libncurses.so.6.2)。这些宽字符库可用于多字节和传统的 8 位语言环境,而普通库只能在 8 位语言环境中正常工作。宽字符库和普通库是源代码兼容的,但不是二进制兼容的。

如果您使用 配置 Ncurses --enable-widec,那么您将libtinfow.so用作 Readline 的链接库。如果您使用非宽版本,那么您将libtinfo.so用作 Readline 的链接库。

如果你用 配置 Ncurses --enable-widec,那么你应该用 配置你的宽 Readline --enable-multibyte。如果您从源代码构建 Bash 并使用广泛的 Readline,那么您应该使用--enable-multibyte. 你要注意细节...

不,同一选项的不同标志 ---enable-widec--enable-multibyte- 是正确的。当您可以添加混乱时,为什么要保持一致?


你可以感谢维护 Ncurses 和 Readline 的人来解决这个问题。他不遵循标准的 GNU 工作流程或 Linux 最佳实践。我鄙视与他坚持的废话一起工作。您将浪费数小时试图弄清楚如何做一些应该简单的事情,例如使用哪些选项,或者让 Readline 使用正确的链接库,或者获得像 BC 或 OpenLDAP 这样的依赖项来正确构建。

另一个宝石是内存泄漏。如果您不幸在 Android 上需要它,那么您可以指望资源耗尽,因为库泄漏了太多内存。Android 通过 JNI 将加载和卸载共享对象数千次,并且由于累积的内存泄漏,您将内存不足。

最后,Ncurses 和 Readline 没有公开的 repo。没有办法针对他的来源提出拉取请求或提供补丁。他的想法git pull是这样的废话:应用补丁

于 2021-01-08T04:52:10.397 回答