GNU/Linux >> Linux の 問題 >  >> Linux

単一ホスト上の複数の glibc ライブラリ

この質問は古く、他の回答は古いです。 「雇用されたロシア人」の回答は非常に有益で有益ですが、ソースコードがある場合にのみ機能します.そうしないと、当時の代替手段は非常にトリッキーでした。幸いなことに、今日では、patchelf を使用して、この問題に対する簡単な解決策があります (彼の返信の 1 つでコメントされているように)。あなたがしなければならないことは:

$ ./patchelf --set-interpreter /path/to/newglibc/ld-linux.so.2 --set-rpath /path/to/newglibc/ myapp

その後、ファイルを実行するだけです:

$ ./myapp

chroot する必要はありません ありがたいことに、バイナリを手動で編集することもできます。ただし、バイナリ ファイルが変更されるため、パッチを適用する前にバイナリをバックアップすることを忘れないでください。パッチを適用した後、古いパスをインタープリター/rpath に復元することはできません。機能しない場合は、実際に機能するパスが見つかるまでパッチを適用し続ける必要があります...まあ、試行錯誤のプロセスである必要はありません。たとえば、OP の例では、GLIBC_2.3 が必要でした 、そのため、 strings を使用して、そのバージョンを提供するライブラリを簡単に見つけることができます :

$ strings /lib/i686/libc.so.6 | grep GLIBC_2.3
$ strings /path/to/newglib/libc.so.6 | grep GLIBC_2.3

理論的には、システム libc には必要なバージョンがないため、最初の grep は空になり、2 番目の grep はバージョンが myapp であるため GLIBC_2.3 を出力するはずです。 を使用しているので、patchelf できることがわかります そのパスを使用してバイナリを作成します。セグメンテーション違反が発生した場合は、最後にある注をお読みください。

Linuxでバイナリを実行しようとすると、バイナリはリンカー、次にライブラリをロードしようとします。それらはすべてパスおよび/または正しい場所にあるはずです。問題がリンカにあり、バイナリが探しているパスを知りたい場合は、次のコマンドで見つけることができます:

$ readelf -l myapp | grep interpreter
  [Requesting program interpreter: /lib/ld-linux.so.2]                                                                                                                                                                                   

問題がライブラリにある場合、使用されているライブラリを提供するコマンドは次のとおりです:

$ readelf -d myapp | grep Shared
$ ldd myapp 

これにより、バイナリに必要なライブラリが一覧表示されますが、OP の場合と同様に、既にエラーが発生しているため、問題のあるライブラリについては既にご存じでしょう。

「patchelf」は、これら 2 つの問題に関連して、プログラムを実行しようとしているときに遭遇する可能性のあるさまざまな問題に対して機能します。たとえば、次の場合:ELF file OS ABI invalid 、新しいローダー (--set-interpreter コマンドの一部) ここで説明します。もう 1 つの例は、No such file or directory を取得する問題です。 ここに例示されているように、そこにあり実行可能なファイルを実行すると。その特定のケースでは、OP にローダーへのリンクがありませんでしたが、あなたのケースではルート アクセス権がなく、リンクを作成できない可能性があります。新しいインタープリターを設定すると、問題が解決します。

洞察と解決策を提供してくれたEmployed RussianとMichael Pankovに感謝します!

注意 セグメンテーション違反の場合:myapp の場合に該当する可能性があります いくつかのライブラリを使用しており、それらのほとんどは問題ありませんが、そうでないものもあります。それならあなたは patchelf それを新しいディレクトリに移動すると、セグメンテーション違反が発生します。 patchelfしたとき バイナリの場合、いくつかのライブラリが元々別のパスにあったとしても、いくつかのライブラリのパスを変更します。以下の私の例を見てください:

$ ldd myapp
./myapp: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by ./myapp)
./myapp: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./myapp)
        linux-vdso.so.1 =>  (0x00007fffb167c000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f9a9aad2000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f9a9a8ce000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f9a9a6af000)
        libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f9a9a3ab000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f9a99fe6000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f9a9adeb000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f9a99dcf000)

ほとんどのライブラリは /lib/x86_64-linux-gnu/ にあることに注意してください しかし、問題のあるもの (libstdc++.so.6 ) は /usr/lib/x86_64-linux-gnu にあります . myapp をパッチした後 /path/to/mylibs を指す 、セグメンテーション違反が発生しました。何らかの理由で、ライブラリはバイナリと完全に互換性がありません。 myapp以降 /lib/x86_64-linux-gnu/ からコピーしました。 /path/to/mylibs2 へ 、そして libstdc++.so.6 もコピーしました /path/to/mylibs から そこの。それから /path/to/mylibs2 にパッチルフしました 、および myapp 今すぐ動作します。バイナリが異なるライブラリを使用していて、バージョンも異なる場合、状況を修正できないことがあります。 :(しかし、可能であれば、ライブラリを混在させることが方法かもしれません。理想的ではありませんが、たぶん それが動作します。頑張ってください!


LD_PRELOAD を使用します。ライブラリを man lib ディレクトリの外に置き、次を実行します。

LD_PRELOAD='mylibc.so anotherlib.so' program

参照:ウィキペディアの記事


まず、動的にリンクされる各プログラムの最も重要な依存関係はリンカーです。そのため、すべてのライブラリはリンカーのバージョンと一致する必要があります。

簡単な例を見てみましょう:私はいくつかのプログラムを実行するニュースセット ubuntu システムを持っています (私の場合は D コンパイラ - ldc2)。古いCentOSで動かしたいのですが、glibcライブラリが古いので無理です。私は手に入れました

ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.15' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)
ldc2-1.5.0-linux-x86_64/bin/ldc2: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by ldc2-1.5.0-linux-x86_64/bin/ldc2)

すべての依存関係を ubuntu から centos にコピーする必要があります。適切な方法は次のとおりです:

まず、すべての依存関係を確認しましょう:

ldd ldc2-1.5.0-linux-x86_64/bin/ldc2 
    linux-vdso.so.1 =>  (0x00007ffebad3f000)
    librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f965f597000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f965f378000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f965f15b000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f965ef57000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f965ec01000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f965e9ea000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f965e60a000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f965f79f000)

linux-vdso.so.1 は実際のライブラリではないため、気にする必要はありません。

/lib64/ld-linux-x86-64.so.2 はリンカーであり、Linux によって使用され、実行可能ファイルをすべての動的ライブラリとリンクします。

残りのファイルは実際のライブラリであり、リンカーと一緒にそれらすべてを centos のどこかにコピーする必要があります。

すべてのライブラリとリンカーが "/mylibs" ディレクトリにあると仮定しましょう。

ld-linux-x86-64.so.2 - すでに述べたように - はリンカです。動的ライブラリではなく、静的実行可能ファイルです。これを実行して、いくつかのパラメーター (--library-path など) があることも確認できます (後で説明します)。

Linux では、動的にリンクされたプログラムはその名前だけで起動される場合があります。例:

/bin/ldc2

Linux はそのようなプログラムを RAM にロードし、どのリンカが設定されているかをチェックします。通常、64 ビット システムでは、/lib64/ld-linux-x86-64.so.2 です (ファイル システムでは、実際の実行可能ファイルへのシンボリック リンクです)。その後、Linux はリンカーを実行し、動的ライブラリをロードします。 /P>

これを少し変更して、次のようなトリックを行うこともできます:

/mylibs/ld-linux-x86-64.so.2 /bin/ldc2

Linux に特定のリンカを強制的に使用させる方法です。

これで、前述のパラメーター --library-path に戻ることができます

/mylibs/ld-linux-x86-64.so.2 --library-path /mylibs /bin/ldc2

ldc2 を実行し、/mylibs から動的ライブラリをロードします。

これは、選択された (システムのデフォルトではない) ライブラリで実行可能ファイルを呼び出す方法です。


同じシステムに複数のバージョンの glibc が存在する可能性は十分にあります (私たちは毎日そうしています)。

ただし、glibc は多くの部分 (200 以上の共有ライブラリ) で構成されており、すべてが一致する必要があることを知っておく必要があります。そのうちの 1 つは ld-linux.so.2 で、しなければならない libc.so.6 と一致しない場合、表示されているエラーが表示されます。

ld-linux.so.2 への絶対パスは、リンク時に実行可能ファイルにハードコードされており、リンク後に簡単に変更することはできません (更新:patchelf で実行できます。以下のこの回答を参照してください)。

新しい glibc で動作する実行可能ファイルをビルドするには、次のようにします。

g++ main.o -o myapp ... \
   -Wl,--rpath=/path/to/newglibc \
   -Wl,--dynamic-linker=/path/to/newglibc/ld-linux.so.2

-rpath リンカー オプションは、ランタイム ローダーが /path/to/newglibc のライブラリを検索するようにします。 (そのため、LD_LIBRARY_PATH を設定する必要はありません 実行前)、および -dynamic-linker オプションは、正しい ld-linux.so.2 へのパスを「ベイク」します

myapp を再リンクできない場合 アプリケーション (たとえば、サードパーティのバイナリであるため) のすべてが失われるわけではありませんが、よりトリッキーになります。 1 つの解決策は、適切な chroot を設定することです。 そのための環境。もう 1 つの可能性は、rtldi とバイナリ エディターを使用することです。更新:または、patchelf を使用できます。


Linux
  1. Unixの単一のコマンドまたはスクリプトで複数のファイルの名前を変更する方法は??

  2. Ssh –一般的な複数のSsh接続ファイル処理の問題?

  3. SNIを使用してApacheで複数のSSL証明書をホストする

  1. 単一のVPSに複数のWordPressサイトを設定する

  2. 仮想ホストを使用して複数のドメインにサービスを提供

  3. 単一のファイルを複数の場所にscpします

  1. Dockerコンテナで複数のWebサイトをホストする

  2. 複数の img ファイルを単一のループ デバイスとしてマウントする

  3. Unixで単一のコマンドまたはスクリプトで複数のファイルの名前を変更する方法は?