2019/07/05

共有ライブラリの参照状況を確認

dynabook SS SX/15AにNetBSD/i386を入れ、アプリケーションはpkgsrcから入れています。もう1年以上もアプリケーションを更新していなかったので、6月上旬にpkgsrcをCVSでカレントの最新にしてpkg_rolling-replaceで作りなおし始めました。しかし導入済みのアプリケーションが多く、もとより数日で終わるとは思っていませんでしたが、ディスクが溢れたり、毎晩カーネルが落ちて日中の作業が無駄になったりして、6月下旬になっても全更新作業が終わりませんでした。

このままでは何時になったら全更新が完了するのか不安になってきたので、ソースから自前でビルドsるのを止めて、pkginを使って出来合いのバイナリ(2019Q1のpkgsrcからビルドされたもの)をインストールして済ませることにしました。流石にバイナリを入れるだけなので、ソースからビルドするのに比べると圧倒的に速く全更新が完了しました。

しかしpkgsrcのカレントからビルドしたパッケージと、2019Q1のpkgsrcからビルドされたパッケージが混在し、共有ライブラリの参照に不整合が生じてしまいました。不整合に気づくたびに対処していく事で、復旧できるのは確かですが、全体的に不整合が残っているのか解消したのか、判断できず不安が残ります。なんとかしたいので、対処してみました。

実現方法の詳細はともかくとして、やろうとすることは単純です。すなわち/usr/bin/lddで検査して異常がないことを確認するだけです。例えば以下に示す例ではlibclang.so.7が見つからずに「not found」となっています。参照できない状態がなければ問題ないと判断します。
/usr/pkg/qt5/bin/qdoc:
        -lexecinfo.0 => /usr/lib/libexecinfo.so.0
        -lelf.2 => /usr/lib/libelf.so.2
        -lgcc_s.1 => /usr/lib/libgcc_s.so.1
        -lc.12 => /usr/lib/libc.so.12
        -lclang.7 => not found
        -lQt5Core.5 => /usr/pkg/qt5/lib/libQt5Core.so.5
        -lz.1 => /usr/lib/libz.so.1
        -licui18n.63 => /usr/pkg/lib/libicui18n.so.63
        -licuuc.63 => /usr/pkg/lib/libicuuc.so.63
        -licudata.63 => /usr/pkg/lib/libicudata.so.63
        -lpthread.1 => /usr/lib/libpthread.so.1
        -lstdc++.8 => /usr/lib/libstdc++.so.8
        -lm.0 => /usr/lib/libm.so.0
        -lpcre2-16.0 => /usr/pkg/lib/libpcre2-16.so.0
        -lgthread-2.0.0 => /usr/pkg/lib/libgthread-2.0.so.0
        -lglib-2.0.0 => /usr/pkg/lib/libglib-2.0.so.0
        -lpcre.1 => /usr/pkg/lib/libpcre.so.1
        -lintl.1 => /usr/lib/libintl.so.1

/usr/bin/lddの出力から「not found」を見つけるために、簡単なawkスクリプトを準備しました。文字列を検索するだけならgrepでも出来ますが、見つかった文字列の属しているファイル(この例であれば/usr/pkg/qt5/bin/gdoc)が何なのか記録できません。awkスクリプトは次のようなもので、単独のコマンドとして使えるように、実行ビットを立てておきます。
#!/usr/bin/awk -f
/:$/ {
        filename = $0;
}
/not found/ {
        print filename, $0;
}
# [EOF]

共有ライブラリの参照に問題があるのは、動的リンクされた実行ファイルや共有ライブラリだけです。静的リンクされた実行ファイルとかテキストファイルなどは検証する必要がありません。当初は検証対象を限定しようと思っていたのですが、対象ファイルを見つける方法を考えるのが面倒になってきたので、強引ですが、マシン内の全てのファイルを対象とすることにしました。処理に無駄が出ますが、単純な処理で済みますし、結果をファイルに落としておいて最終的に確認すれば良いだけのことです。結局2時間ほどで全ファイルの検証が終わりました。

この検証をおこなったコマンドは以下の通りです。上述したawkスクリプトは「notfound.awk」というコマンドにしています。
find / -type f | sed -e 's/^/ldd "/' -e 's/$/"/' | sh 2>&1 | notfound.awk > notfound.log

findで対象を見つけた場合には、xargsでコマンドに渡すのが定番です。しかしsedshを組み合わせてコマンドを動かしています。当初はxargsを使おうと思っていたのですが、Microsoft Windows由来のファイルがあり、ファイル名の中に空白文字が含まれるため、findxargsの組み合わせでは、処理できなかったのです。

結果を記録されたファイルには、予想していたよりも相当多いファイル名が記録されていました。しかし/usr/pkg/opt/usr/pkg/emul/linuxなどにあるLinux版ファイルが大多数を占めており、本当に問題があったのは数ファイルだけでした。それらは対処したので、不整合の問題は解決した(それ以外に起因する問題は残りますが)と思います。

0 件のコメント:

コメントを投稿