ほぼ雑記的メモ
秘伝のタレのように継ぎ足しながら運用しているFreeBSDにありがちな問題。以前もあったんですが、またまたupgradeで動かない問題。今回は以下のようなエラーが発生しました
# bashld-elf.so.1: Undefined symbol "rl_sort_completion_matches" referenced from COPY relocation in /usr/local/bin/bash
# bash
ld-elf.so.1: Undefined symbol "rl_sort_completion_matches" referenced from COPY relocation in /usr/local/bin/bash
こんな感のエラーです。例によって問題は/lib以下に残っている古いライブラリなんでしょうけど、この探り方についてのメモを残しておきます。まずこのエラーが一体なんなのか?という説明。
多くのプログラムはdynamic linkというものを使ってビルドされています。これは実行時にlibraryをリンクするというもので最近の主流となっているものです。これの真逆はstatic linkで実行ファイルを作成するときにlibraryも一緒にリンクしちゃうことです。dynamic linkにすることでバイナリサイズを小さくできますし、ライブラリにバグが見つかったときでもライブラリだけの更新で済むと言う利点があります。
一方、dynamic linkは正しくlinkされないとダメということで同じ名前のライブラリが別なディレクトリなどにあったりするとうまく整合性が取れずこのようなエラーが発生している・・と予想できます。
実行ファイルやライブラリには、プログラム本体の他に「シンボル」と呼ばれる情報があります。シンボルというのは簡単にいえば関数名のようなもので、実行ファイルとライブラリのシンボル名を実行時にリンクして解決することで初めてプログラムがメモリ上に配置され実行できるようになるわけです。それを出力するコマンドが nmです。
nm -D /usr/local/bin/bash
を実行すると以下のような箇所がありました。
00000000002fac00 B rl_signal_event_hook00000000002fabdc B rl_sort_completion_matches00000000002f7b00 B rl_special_prefixes00000000002fac10 B rl_startup_hook
00000000002fac00 B rl_signal_event_hook
00000000002fabdc B rl_sort_completion_matches
00000000002f7b00 B rl_special_prefixes
00000000002fac10 B rl_startup_hook
左の数字はプログラムにおけるアドレスで右がシンボルになります。真ん中のBがそのシンボルの状態を表す記号。この場合BですのでBSSセクションに配置されているということになります。BSSセクションとはなんぞや?とかなるとリンカ沼にハマるので詳しくは解説しません・・(というか解説できません。私が知ってるのはDATAとかTEXTとか古くからあるやつだけでこいつらはプレステでゲーム作ってるときは重要だった。今はどうなんだろ?)。まぁ状態ということで認識しておけばよいかと思います。ちなみにBは解決済みです。じゃぁなんでエラーがでるんでしょうか?
そこでエラーメッセージに戻ります
COPY
の文字。これは「COPY relocation」という仕組みに関するエラーで領域はプログラム側に予約されているけれど、実体はライブラリ側にあるということです。それがうまく解決できていないと。
名称からしてreadlineの保管の問題っぽいので /libのあたりから探りをいれていきます。
/lib
ldd コマンドで何がリンクされているのかを確認します
# ldd /usr/local/bin/bash/usr/local/bin/bash: libreadline.so.8 => /lib/libreadline.so.8 (0x3762cef30000) libhistory.so.8 => /usr/lib/libhistory.so.8 (0x3762cf42e000) libncursesw.so.9 => /lib/libncursesw.so.9 (0x3762d0296000) libintl.so.8 => /usr/local/lib/libintl.so.8 (0x3762d1029000) libdl.so.1 => /usr/lib/libdl.so.1 (0x3762d1e18000) libc.so.7 => /lib/libc.so.7 (0x3762d2de0000) libncurses.so.8 => /lib/libncurses.so.8 (0x3762d33ca000) libthr.so.3 => /lib/libthr.so.3 (0x3762d3d5e000) [vdso] (0x7ffffffff650)
# ldd /usr/local/bin/bash
/usr/local/bin/bash:
libreadline.so.8 => /lib/libreadline.so.8 (0x3762cef30000)
libhistory.so.8 => /usr/lib/libhistory.so.8 (0x3762cf42e000)
libncursesw.so.9 => /lib/libncursesw.so.9 (0x3762d0296000)
libintl.so.8 => /usr/local/lib/libintl.so.8 (0x3762d1029000)
libdl.so.1 => /usr/lib/libdl.so.1 (0x3762d1e18000)
libc.so.7 => /lib/libc.so.7 (0x3762d2de0000)
libncurses.so.8 => /lib/libncurses.so.8 (0x3762d33ca000)
libthr.so.3 => /lib/libthr.so.3 (0x3762d3d5e000)
[vdso] (0x7ffffffff650)
ここで/libの下をみてみると
-r--r--r-- 1 root wheel 273064 Aug 28 2018 libreadline.so.8
というファイルがありました。あやしいです。これだけ2018年。
こではFreeBSDのアップデートの仕組みが関係しているようです。FeeBSDはfreebsd-update でアップデートをしたとしても古いライブラリをアップデートの際に削除しないようです(あるいはしていなかった?裏とってません)。つまりバージョンがあがって最新バージョンで無くなったとしてもそのライブラリは残しているわけです。削除してしまうとそのライブラリをリンクして動作していたプログラムが動かなくなるからということかと思いますがこれが秘伝のタレのような運用をしているサーバに悪影響を与えるわけです。
bashに関していえば /usr/local/lib/以下にもpkgから入れられたlibreadlineが存在しています。こちらをリンクするようにすれば解決するものと思われます。念の為コマンドをタイプ
/usr/local/lib/
libreadline
# nm -D /usr/local/lib/libreadline.so.8 | grep rl_sort_completion_0000000000051114 D rl_sort_completion_matches# nm -D /lib/libreadline.so.8 | grep rl_sort_completion_
# nm -D /usr/local/lib/libreadline.so.8 | grep rl_sort_completion_
0000000000051114 D rl_sort_completion_matches
# nm -D /lib/libreadline.so.8 | grep rl_sort_completion_
/usr/loca/lib/以下のほうには存在するようです。そこで強引にこちらのライブラリを優先的に検索するようにしてみます
env LD_LIBRARY_PATH=/usr/local/lib bash
はい、動きました。あとは /lib/libreadline.so.8をどうするかだけを考えればよいわけですが、基本的にpkgだけでアプリをいれているサーバなんでそんなものを使っているものが残っているはずもない・・ということでガッツリ削除することにしました。 ls -ltでタイムスタンプで並べ直してみると
ls -lt
-r--r--r-- 1 root wheel 314744 Dec 30 2022 libzfs.so.3-r--r--r-- 1 root wheel 31800 Dec 30 2022 libufs.so.6-r--r--r-- 1 root wheel 387320 Dec 30 2022 libncursesw.so.8-r--r--r-- 1 root wheel 349640 Dec 30 2022 libncurses.so.8-r--r--r-- 1 root wheel 216728 Dec 30 2022 libedit.so.7-r--r--r-- 1 root wheel 273064 Aug 28 2018 libreadline.so.8-r--r--r-- 1 root wheel 37000 Aug 28 2018 libkvm.so.6-r--r--r-- 1 root wheel 7736 Aug 28 2018 libipx.so.5-r--r--r-- 1 root wheel 2055072 Aug 28 2018 libcrypto.so.7-r--r--r-- 1 root wheel 192040 Aug 28 2018 libcam.so.6-r--r--r-- 1 root wheel 1722192 Apr 9 2014 libcrypto.so.6-r--r--r-- 1 root wheel 34728 Dec 4 2012 libkvm.so.5-r--r--r-- 1 root wheel 68360 Dec 4 2012 libmd.so.5
-r--r--r-- 1 root wheel 314744 Dec 30 2022 libzfs.so.3
-r--r--r-- 1 root wheel 31800 Dec 30 2022 libufs.so.6
-r--r--r-- 1 root wheel 387320 Dec 30 2022 libncursesw.so.8
-r--r--r-- 1 root wheel 349640 Dec 30 2022 libncurses.so.8
-r--r--r-- 1 root wheel 216728 Dec 30 2022 libedit.so.7
-r--r--r-- 1 root wheel 37000 Aug 28 2018 libkvm.so.6
-r--r--r-- 1 root wheel 7736 Aug 28 2018 libipx.so.5
-r--r--r-- 1 root wheel 2055072 Aug 28 2018 libcrypto.so.7
-r--r--r-- 1 root wheel 192040 Aug 28 2018 libcam.so.6
-r--r--r-- 1 root wheel 1722192 Apr 9 2014 libcrypto.so.6
-r--r--r-- 1 root wheel 34728 Dec 4 2012 libkvm.so.5
-r--r--r-- 1 root wheel 68360 Dec 4 2012 libmd.so.5
いやー結構ありますね。10年以上前から残っている秘伝のタレlibraryがたくさん・・・
これら全部削除してよいものだと思います。トラブルのもとなので。というか、たまたま動いているだけで、意図せずメンテナンスされていない古いライブラリが使われている可能性もあります。これはこれで問題ですよね?
OpenAIにイラスト描いてもらいました