206

私の Linux (SLES-8) サーバーには現在 glibc-2.2.5-235 がありますが、このバージョンでは動作せず、glibc-2.3.3 を必要とするプログラムがあります。

同じホストに複数の glibc をインストールすることは可能ですか?

これは、古い glibc でプログラムを実行したときに発生するエラーです。

./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./myapp)
./myapp: /lib/i686/libpthread.so.0: version `GLIBC_2.3.2' not found (required by ./myapp)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libxerces-c.so.27)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)
./myapp: /lib/i686/libc.so.6: version `GLIBC_2.3' not found (required by ./libstdc++.so.6)

そこで、newglibc という新しいディレクトリを作成し、次のファイルをコピーしました。

libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so

export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH

しかし、私はエラーが発生します:

./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libpthread.so.0)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by libstdc++.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libm.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_2.3' not found (required by ./newglibc/libc.so.6)
./myapp: /lib/ld-linux.so.2: version `GLIBC_PRIVATE' not found (required by ./newglibc/libc.so.6)

そのため、それらはまだリンクして/libいて、私が置いた場所からピックアップしていないようです.

4

11 に答える 11

276

同じシステム上に複数のバージョンの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を使用できます。

于 2009-05-12T05:10:45.170 に答える
103

この質問は古く、他の回答は古いです。「雇用されたロシア人」の回答は非常に有益で有益ですが、ソースコードがある場合にのみ機能します. そうしないと、当時の代替手段は非常にトリッキーでした。幸いなことに、今日では、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 は GLIBC_2.3 を出力する必要があります。これは、バージョンが使用されているためです。したがって、そのパスを使用してバイナリを使用myappできることがわかります。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コマンドの一部) を設定することで修正される場合があります。別の例は、ここに例示されているように、そこにあり実行可能なファイルを実行したときに取得するという問題です。その特定のケースでは、OP にローダーへのリンクがありませんでしたが、あなたのケースではルート アクセス権がなく、リンクを作成できない可能性があります。新しいインタープリターを設定すると、問題が解決します。No such file or directory

洞察力と解決策を提供してくれた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) は on であることに注意してください/usr/lib/x86_64-linux-gnumyappを指すようにパッチルフした後/path/to/mylibs、セグメンテーション違反が発生しました。何らかの理由で、ライブラリはバイナリと完全に互換性がありません。myapp元のライブラリについて文句を言わなかったので、 から/lib/x86_64-linux-gnu/にコピーし、そこから/path/to/mylibs2もコピーしました。それから私はそれを にパッチルフし、現在動作しています。バイナリが異なるライブラリを使用していて、バージョンも異なる場合、状況を修正できないことがあります。:(しかし、可能であれば、ライブラリを混在させることが方法かもしれません。理想的ではありませんが、うまくいくかもしれません。頑張ってください!libstdc++.so.6/path/to/mylibs/path/to/mylibs2myapp

于 2017-06-22T23:01:36.267 に答える
20

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

LD_PRELOAD='mylibc.so anotherlib.so' program

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

于 2009-05-11T22:36:00.120 に答える
7

@msb は安全な解決策を提供します。

のみを持つimport tensorflow as tfconda環境で行ったときに、この問題に遭遇しました。CentOS 6.5glibc-2.12

ImportError: /lib64/libc.so.6: version `GLIBC_2.16' not found (required by /home/

いくつかの詳細を提供したい:

まずglibc、ホーム ディレクトリにインストールします。

mkdir ~/glibc-install; cd ~/glibc-install
wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz
tar -zxvf glibc-2.17.tar.gz
cd glibc-2.17
mkdir build
cd build
../configure --prefix=/home/myself/opt/glibc-2.17  # <-- where you install new glibc
make -j<number of CPU Cores>  # You can find your <number of CPU Cores> by using **nproc** command
make install

次に、同じ方法でpatchelfをインストールします。

3 番目に、Python にパッチを適用します。

[myself@nfkd ~]$ patchelf --set-interpreter /home/myself/opt/glibc-2.17/lib/ld-linux-x86-64.so.2 --set-rpath /home/myself/opt/glibc-2.17/lib/ /home/myself/miniconda3/envs/tensorflow/bin/python

@msbで述べたように

で使えるようtensorflow-2.0 alphaになりましたCentOS 6.5

参照: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/

于 2019-04-13T07:14:53.130 に答える
6

Nix http://nixos.org/nix/ の使用を検討できますか?

Nix はマルチユーザー パッケージ管理をサポートしています。複数のユーザーが共通の Nix ストアを安全に共有でき、ソフトウェアをインストールするためにルート権限を持っている必要はなく、異なるバージョンのパッケージをインストールして使用できます。

于 2014-08-31T11:10:46.817 に答える
1

2 番目の出力をよく見ると、ライブラリの新しい場所が使用されていることがわかります。glibc の一部であるライブラリがまだ不足している可能性があります。

また、プログラムで使用されるすべてのライブラリは、そのバージョンの glibc に対してコンパイルする必要があると思います。プログラムのソース コードにアクセスできる場合は、新しいコンパイルが最適なソリューションのようです。

于 2009-05-11T11:46:06.577 に答える
1

「雇用されたロシア人」が最良の回答の 1 つであり、他の提案された回答はすべてうまくいかない可能性があると思います。その理由は単純で、アプリケーションが最初に作成されるときに、必要なすべての API がコンパイル時に解決されるためです。「ldd」を使用すると、静的にリンクされたすべての依存関係を確認できます。

ldd /usr/lib/firefox/firefox
    linux-vdso.so.1 =>  (0x00007ffd5c5f0000)
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f727e708000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f727e500000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f727e1f8000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f727def0000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f727db28000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f727eb78000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f727d910000)

しかし、実行時に、Firefox は他の多くの動的ライブラリもロードします。たとえば、(Firefox の場合) 多くの "glib" ラベルのライブラリがロードされます (静的にリンクされているライブラリはありません):

 /usr/lib/x86_64-linux-gnu/libdbus-glib-1.so.2.2.2
 /lib/x86_64-linux-gnu/libglib-2.0.so.0.4002.0
 /usr/lib/x86_64-linux-gnu/libavahi-glib.so.1.0.2

多くの場合、あるバージョンの名前が別のバージョンにソフト リンクされていることがわかります。例えば:

lrwxrwxrwx 1 root root     23 Dec 21  2014 libdbus-glib-1.so.2 -> libdbus-glib-1.so.2.2.2
-rw-r--r-- 1 root root 160832 Mar  1  2013 libdbus-glib-1.so.2.2.2

したがって、これは 1 つのシステムに異なるバージョンの「ライブラリ」が存在することを意味します。これは同じファイルであるため問題ではなく、アプリケーションに複数のバージョンの依存関係がある場合に互換性を提供します。

したがって、システム レベルでは、すべてのライブラリは互いにほぼ相互依存しており、LD_PRELOAD または LD_LIBRARY_PATH を操作してライブラリのロード優先度を変更するだけでは役に立ちません。ロードできても、実行時にクラッシュする可能性があります。

http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc

最良の代替手段はchrootです(ERで簡単に言及されています):ただし、これには、元のバイナリ実行である環境全体を再作成する必要があります-通常は/ lib、/ usr/lib /、/ usr/lib/x86などから開始します. 「Buildroot」または YoctoProject を使用するか、既存の Distro 環境から単に tar を使用できます。(Fedora/Suse など)。

于 2015-07-08T16:32:31.427 に答える