Beberapa pustaka glibc pada satu host
Server linux (SLES-8) saya saat ini memiliki glibc-2.2.5-235, tetapi saya memiliki program yang tidak dapat digunakan pada versi ini dan membutuhkan glibc-2.3.3.
Apakah mungkin untuk menginstal beberapa glibcs pada host yang sama?
Ini adalah kesalahan yang saya dapatkan ketika saya menjalankan program saya di glibc lama:
./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)
Jadi saya membuat direktori baru bernama newglibc dan menyalin file-file berikut ke:
libpthread.so.0
libm.so.6
libc.so.6
ld-2.3.3.so
ld-linux.so.2 -> ld-2.3.3.so
dan
export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH
Tapi saya mendapat kesalahan:
./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)
Jadi sepertinya mereka masih terhubung ke / lib dan tidak mengambil dari tempat saya meletakkannya?
Terima kasih
export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH
memang memecahkan masalah bagi saya! Ini tentu saja tidak akan berhasil untuk semua orang, tetapi ini adalah perbaikan yang mudah jika berhasil! Terima kasih! :)Jawaban:
Sangat mungkin untuk memiliki beberapa versi glibc pada sistem yang sama (kami melakukannya setiap hari).
Namun, Anda perlu tahu bahwa glibc terdiri dari banyak bagian (200+ pustaka bersama) yang semuanya harus cocok. Salah satunya adalah ld-linux.so.2, dan itu harus cocok dengan libc.so.6, atau Anda akan melihat kesalahan yang Anda lihat.
Path absolut ke ld-linux.so.2 adalah hard-coded menjadi executable pada waktu link, dan tidak dapat dengan mudah diubah setelah tautan selesai.
Untuk membangun yang dapat dieksekusi yang akan bekerja dengan glibc baru, lakukan ini:
The
-rpath
pilihan linker akan membuat runtime pencarian loader untuk perpustakaan di/path/to/newglibc
(sehingga Anda tidak perlu setLD_LIBRARY_PATH
sebelum menjalankannya), dan-dynamic-linker
pilihan akan "panggang" jalan untuk benarld-linux.so.2
ke dalam aplikasi.Jika Anda tidak dapat menautkan kembali
myapp
aplikasi (mis. Karena ini adalah biner pihak ketiga), tidak semua hilang, tetapi akan semakin rumit. Salah satu solusinya adalah menetapkanchroot
lingkungan yang tepat untuknya. Kemungkinan lain adalah menggunakan rtldi dan editor biner .sumber
-Wl,--dynamic-linker=file
(butuh dua '-') hanya berfungsi saat kompilasi untuk executable ELF. Periksa/sbin/ldconfig -p | grep ld
patchelf
( nixos.org/patchelf.html ), yang memungkinkan Anda untuk memodifikasi rpath dan interpreter dari ELF yang sudah dikompilasi.-Wl,--rpath
daripadaLD_LIBRARY_PATH
penting untuk alasan lain selain kenyamanan: jika program meluncurkan proses anak, nilaiLD_LIBRARY_PATH
biasanya akan diwarisi oleh mereka, tetapi jika mereka juga tidak dikompilasi untuk menggunakan glibc yang lebih baru (misalnya, jika mereka seperti binari sahambash
), mereka tidak akan diluncurkan./path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
-I
dan-L
: stackoverflow.com/a/52454603/895245Pertanyaan ini sudah tua, jawaban yang lain sudah tua. Jawaban "Employed Russian" sangat bagus dan informatif, tetapi hanya berfungsi jika Anda memiliki kode sumber. Jika tidak, alternatif saat itu sangat sulit. Untungnya saat ini kami memiliki solusi sederhana untuk masalah ini (seperti yang dikomentari dalam salah satu balasannya), menggunakan patchelf . Yang harus Anda lakukan adalah:
Dan setelah itu, Anda bisa menjalankan file Anda:
chroot
Untungnya, tidak perlu atau secara manual mengedit binari. Tapi ingat untuk membuat cadangan biner Anda sebelum menambalnya, jika Anda tidak yakin apa yang Anda lakukan, karena memodifikasi file biner Anda. Setelah Anda menambalnya, Anda tidak dapat mengembalikan jalur lama ke interpreter / rpath. Jika tidak berhasil, Anda harus terus menambalnya sampai Anda menemukan jalan yang benar-benar berfungsi ... Yah, itu tidak harus menjadi proses coba-coba. Misalnya, dalam contoh OP, ia perluGLIBC_2.3
, sehingga Anda dapat dengan mudah menemukan lib yang menyediakan versi itu menggunakanstrings
:Secara teori, grep pertama akan kosong karena sistem libc tidak memiliki versi yang diinginkannya, dan grep ke-2 harus menampilkan GLIBC_2.3 karena memiliki versi
myapp
yang digunakan, jadi kami tahupatchelf
bahwa biner kami dapat menggunakan jalur itu.Ketika Anda mencoba menjalankan biner di linux, biner mencoba memuat tautan, lalu pustaka, dan semuanya harus berada di jalur dan / atau di tempat yang tepat. Jika masalah Anda ada pada tautan dan Anda ingin mencari tahu jalur mana yang dicari biner Anda, Anda bisa mengetahuinya dengan perintah ini:
Jika masalah Anda dengan libs, perintah yang akan memberi Anda libs yang digunakan adalah:
Ini akan mencantumkan lib yang dibutuhkan biner Anda, tetapi Anda mungkin sudah tahu yang bermasalah, karena mereka sudah menghasilkan kesalahan seperti dalam kasus OP.
"patchelf" berfungsi untuk banyak masalah berbeda yang mungkin Anda temui saat mencoba menjalankan suatu program, terkait dengan 2 masalah ini. Misalnya, jika Anda mendapatkan
ELF file OS ABI invalid
:, mungkin diperbaiki dengan menetapkan loader baru (--set-interpreter
bagian dari perintah) seperti yang saya jelaskan sini . Contoh lain adalah untuk masalah mendapatkanNo such file or directory
ketika Anda menjalankan file yang ada dan dapat dieksekusi, seperti dicontohkan di sini . Dalam kasus khusus itu, OP tidak memiliki tautan ke loader, tetapi mungkin dalam kasus Anda Anda tidak memiliki akses root dan tidak dapat membuat tautan. Mengatur juru bahasa baru akan menyelesaikan masalah Anda.Terima kasih Mempekerjakan Rusia dan Michael Pankov untuk wawasan dan solusi!
sumber
patchelf
), tetapi frasa "Tidak perlu ... mengedit binari" mungkin sedikit menyesatkan (karena Anda sebenarnya mengedit binari Anda).Gunakan LD_PRELOAD: letakkan perpustakaan Anda di suatu tempat dari direktori man lib dan jalankan:
Lihat: artikel Wikipedia
sumber
Pertama-tama, ketergantungan paling penting dari setiap program yang terhubung secara dinamis adalah penghubung. Semua perpustakaan harus cocok dengan versi tautannya.
Mari kita ambil contoh sederhana: Saya memiliki sistem ubuntu newset tempat saya menjalankan beberapa program (dalam kasus saya ini adalah kompiler D - ldc2). Saya ingin menjalankannya di CentOS lama, tetapi karena pustaka glibc yang lebih lama, itu tidak mungkin. saya mendapatkan
Saya harus menyalin semua dependensi dari ubuntu ke centos. Metode yang tepat adalah sebagai berikut:
Pertama, mari kita periksa semua dependensi:
linux-vdso.so.1 bukan perpustakaan nyata dan kami tidak perlu mempedulikannya.
/lib64/ld-linux-x86-64.so.2 adalah linker, yang digunakan oleh linux do link yang dapat dieksekusi dengan semua pustaka dinamis.
Sisa file adalah perpustakaan nyata dan semuanya bersama dengan linker harus disalin di suatu tempat di centos.
Mari kita asumsikan semua perpustakaan dan tautan ada di direktori "/ mylibs".
ld-linux-x86-64.so.2 - seperti yang sudah saya katakan - adalah penghubungnya. Ini bukan perpustakaan dinamis tetapi dieksekusi statis. Anda dapat menjalankannya dan melihat bahwa ia bahkan memiliki beberapa parameter, misalnya --library-path (saya akan kembali ke sana).
Di linux, program yang terhubung secara dinamis dapat disantap hanya dengan namanya, misalnya
Linux memuat program tersebut ke dalam RAM, dan memeriksa linker mana yang diatur untuk itu. Biasanya, pada sistem 64-bit, ini adalah /lib64/ld-linux-x86-64.so.2 (dalam sistem file Anda ini adalah tautan simbolis ke executable yang sebenarnya). Kemudian linux menjalankan linker dan memuat pustaka dinamis.
Anda juga dapat mengubah ini sedikit dan melakukan trik seperti itu:
Ini adalah metode untuk memaksa linux menggunakan penghubung tertentu.
Dan sekarang kita dapat kembali ke parameter yang disebutkan sebelumnya --library-path
Ini akan menjalankan ldc2 dan memuat pustaka dinamis dari / mylibs.
Ini adalah metode untuk memanggil executable dengan pustaka yang dipilih (bukan sistem default).
sumber
Setup 1: kompilasi glibc Anda sendiri tanpa GCC khusus dan gunakan
Penyiapan ini mungkin berfungsi dan cepat karena tidak mengkompilasi ulang seluruh rantai alat GCC, hanya glibc.
Tapi itu tidak dapat diandalkan karena menggunakan tuan C runtime objek seperti
crt1.o
,crti.o
, dancrtn.o
disediakan oleh glibc. Ini disebutkan di: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location Benda-benda itu melakukan penyetelan awal yang bergantung pada glibc, jadi saya tidak akan terkejut jika ada hal-hal yang terjadi pada glibc, dan cara-cara yang sangat halus.Untuk pengaturan yang lebih andal, lihat Pengaturan 2 di bawah ini.
Bangun glibc dan instal secara lokal:
Setup 1: verifikasi build
test_glibc.c
Kompilasi dan jalankan dengan
test_glibc.sh
:Program menghasilkan yang diharapkan:
Perintah diadaptasi dari https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_location tetapi
--sysroot
membuatnya gagal dengan:jadi saya menghapusnya.
ldd
output mengonfirmasi bahwaldd
pustaka dan yang baru saja kita bangun sebenarnya digunakan seperti yang diharapkan:The
gcc
kompilasi men-debug output yang menunjukkan bahwa host saya objek runtime yang digunakan, yang buruk seperti yang disebutkan sebelumnya, tapi saya tidak tahu bagaimana bekerja di sekitarnya, misalnya mengandung:Pengaturan 1: modifikasi glibc
Sekarang mari kita ubah glibc dengan:
Kemudian mengkompilasi ulang dan menginstal ulang glibc, dan mengkompilasi ulang dan menjalankan kembali program kami:
dan kami melihat
hacked
dicetak beberapa kali seperti yang diharapkan.Ini lebih lanjut menegaskan bahwa kami benar-benar menggunakan glibc yang kami kompilasi dan bukan yang host.
Diuji pada Ubuntu 18.04.
Pengaturan 2: pengaturan murni crosstool-NG
Ini adalah sebuah alternatif untuk setup 1, dan itu adalah setup yang benar yang paling saya telah mencapai jauh: semuanya sudah benar sejauh yang saya dapat mengamati, termasuk runtime C objek seperti
crt1.o
,crti.o
, dancrtn.o
.Dalam pengaturan ini, kami akan mengkompilasi toolchain GCC khusus yang menggunakan glibc yang kami inginkan.
Satu-satunya downside ke metode ini adalah bahwa pembangunan akan memakan waktu lebih lama. Tapi saya tidak akan mengambil risiko setup produksi dengan sesuatu yang kurang.
crosstool-NG adalah sekumpulan skrip yang mengunduh dan mengkompilasi semuanya dari sumber untuk kita, termasuk GCC, glibc dan binutils.
Ya sistem build GCC sangat buruk sehingga kami membutuhkan proyek terpisah untuk itu.
Pengaturan ini hanya tidak sempurna karena crosstool-NG tidak mendukung pembuatan executable tanpa
-Wl
flag tambahan , yang terasa aneh karena kami telah membangun GCC sendiri. Tapi semuanya sepertinya berhasil, jadi ini hanya ketidaknyamanan.Dapatkan crosstool-NG, konfigurasikan dan bangun:
Pembangunan memakan waktu sekitar tiga puluh menit hingga dua jam.
Satu-satunya opsi konfigurasi wajib yang dapat saya lihat, adalah membuatnya cocok dengan versi kernel host Anda untuk menggunakan header kernel yang benar. Temukan versi kernel host Anda dengan:
yang menunjukkan saya:
jadi di
menuconfig
saya lakukan:Operating System
Version of linux
jadi saya pilih:
yang merupakan versi sama atau lebih tua pertama. Itu harus lebih tua karena kernel kompatibel.
Setup 2: konfigurasi opsional
Yang
.config
kami hasilkan./ct-ng x86_64-unknown-linux-gnu
memiliki:Untuk mengubahnya,
menuconfig
lakukan:C-library
Version of glibc
Selamatkan
.config
, dan lanjutkan dengan membangun.Atau, jika Anda ingin menggunakan sumber glibc Anda sendiri, misalnya untuk menggunakan glibc dari git terbaru, lanjutkan seperti ini :
Paths and misc options
Try features marked as EXPERIMENTAL
: disetel ke trueC-library
Source of glibc
Custom location
: bilang iyaCustom location
Custom source location
: arahkan ke direktori yang mengandung sumber glibc Andadi mana glibc dikloning sebagai:
Setup 2: ujilah
Setelah Anda membangun rantai alat yang Anda inginkan, ujilah dengan:
Semuanya tampaknya berfungsi seperti dalam Pengaturan 1, kecuali bahwa sekarang objek runtime yang benar digunakan:
Penyiapan 2: upaya rekompilasi glibc gagal yang efisien
Tampaknya tidak mungkin dengan crosstool-NG, seperti yang dijelaskan di bawah ini.
Jika Anda hanya membangun kembali;
maka perubahan Anda ke lokasi sumber glibc khusus diperhitungkan, tetapi itu membangun semuanya dari awal, sehingga tidak dapat digunakan untuk pengembangan berulang.
Jika kita melakukannya:
ini memberikan gambaran bagus tentang langkah-langkah pembuatan:
oleh karena itu, kita melihat bahwa ada langkah-langkah glibc yang terkait dengan beberapa langkah GCC, terutama
libc_start_files
datang sebelumnyacc_core_pass_2
, yang kemungkinan merupakan langkah paling mahal bersama dengancc_core_pass_1
.Untuk membangun hanya satu langkah, Anda harus terlebih dahulu mengatur opsi "Simpan langkah-langkah lanjutan" di
.config
untuk membangun awal:Paths and misc options
Debug crosstool-NG
Save intermediate steps
dan kemudian Anda dapat mencoba:
tapi sayangnya,
+
diperlukan seperti yang disebutkan di: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536dan pada dasarnya masih membuat pembangunan kembali terlalu lambat untuk dapat dikembangkan, dan saya tidak melihat cara mengatasinya tanpa menambal crosstool-NG.
Lebih jauh lagi, mulai dari
libc
langkah sepertinya tidak menyalin dari sumber lagi dariCustom source location
, lebih lanjut membuat metode ini tidak dapat digunakan.Bonus: stdlibc ++
Bonus jika Anda juga tertarik dengan pustaka standar C ++: Bagaimana cara mengedit dan membangun kembali sumber libstdc GCC ++ C ++ standar?
sumber
Bisakah Anda mempertimbangkan menggunakan Nix http://nixos.org/nix/ ?
sumber
@msb memberikan solusi yang aman.
Saya menemukan masalah ini ketika saya melakukannya
import tensorflow as tf
di lingkungan condaCentOS 6.5
yang hanya memilikiglibc-2.12
.Saya ingin memberikan beberapa detail:
Pertama instal
glibc
ke direktori home Anda:Kedua, ikuti cara yang sama untuk menginstal patchelf ;
Ketiga, tempel Python Anda:
seperti yang disebutkan oleh @msb
Sekarang saya dapat menggunakan
tensorflow-2.0 alpha
diCentOS 6.5
.ref: https://serverkurma.com/linux/how-to-update-glibc-newer-version-on-centos-6-x/
sumber
Saya tidak yakin pertanyaannya masih relevan, tetapi ada cara lain untuk memperbaiki masalah: Docker. Seseorang dapat menginstal wadah yang hampir kosong dari Distribusi Sumber (Distribusi yang digunakan untuk pengembangan) dan menyalin file ke Kontainer. Dengan begitu Anda tidak perlu membuat sistem file yang dibutuhkan untuk chroot.
sumber
Jika Anda melihat dekat pada output kedua Anda dapat melihat bahwa lokasi baru untuk perpustakaan digunakan. Mungkin masih ada perpustakaan yang hilang yang merupakan bagian dari glibc.
Saya juga berpikir bahwa semua perpustakaan yang digunakan oleh program Anda harus dikompilasi terhadap versi glibc. Jika Anda memiliki akses ke kode sumber program, kompilasi baru tampaknya menjadi solusi terbaik.
sumber
"Mempekerjakan bahasa Rusia" adalah salah satu jawaban terbaik, dan saya pikir semua jawaban yang disarankan lainnya mungkin tidak berfungsi. Alasannya hanya karena ketika aplikasi pertama kali dibuat, semua API yang dibutuhkannya diselesaikan pada waktu kompilasi. Menggunakan "ldd" u dapat melihat semua dependensi yang terhubung secara statis:
Tetapi pada saat runtime, firefox juga akan memuat banyak pustaka dinamis lain, misal (untuk firefox) ada banyak pustaka berlabel "glib" yang dimuat (walaupun terhubung secara statis tidak ada):
Sering kali, Anda dapat melihat nama-nama dari satu versi dihubungkan dengan lembut ke versi lain. Misalnya:
Karena itu ini berarti versi "libraries" yang berbeda ada dalam satu sistem - yang tidak menjadi masalah karena merupakan file yang sama, dan itu akan memberikan kompatibilitas ketika aplikasi memiliki banyak versi dependensi.
Oleh karena itu, pada tingkat sistem, semua pustaka hampir saling bergantung satu sama lain, dan hanya mengubah pustaka yang memuat prioritas melalui memanipulasi LD_PRELOAD atau LD_LIBRARY_PATH tidak akan membantu - meskipun ia dapat memuat, meskipun ia dapat memuat, runtime mungkin masih macet.
http://lightofdawn.org/wiki/wiki.cgi/-wiki/NewAppsOnOldGlibc
Alternatif terbaik adalah chroot (disebutkan secara singkat oleh ER): tetapi untuk ini Anda harus membuat ulang seluruh lingkungan yang merupakan biner eksekusi aslinya - biasanya mulai dari / lib, / usr / lib /, / usr / lib / x86 dll. Anda dapat menggunakan "Buildroot", atau YoctoProject, atau hanya tar dari lingkungan Distro yang ada. (seperti Fedora / Suse dll).
sumber
Ketika saya ingin menjalankan chromium-browser di Ubuntu (glibc-2.15), saya mendapatkan pesan (khas) "... libc.so.6: versi` GLIBC_2.19 'not found ... ". Saya mempertimbangkan fakta, bahwa file tidak diperlukan secara permanen, tetapi hanya untuk memulai. Jadi saya mengumpulkan file yang diperlukan untuk browser dan sudo dan menciptakan lingkungan mini-glibc-2.19-, memulai browser dan kemudian menyalin kembali file aslinya. File yang dibutuhkan dalam RAM dan glibc asli adalah sama.
mkdir -p /glibc-2.19/i386-linux-gnu
mkdir -p /glibc-2.15/i386-linux-gnu
skrip untuk menjalankan browser:
sumber