एक ही मेजबान पर कई glibc पुस्तकालयों


171

एक ही मेजबान पर कई glibc पुस्तकालयों

मेरे लिनक्स (SLES-8) सर्वर में वर्तमान में glibc-2.2.5-235 है, लेकिन मेरा एक प्रोग्राम है जो इस संस्करण पर काम नहीं करेगा और इसके लिए glibc-2.3.3 की आवश्यकता है।

क्या एक ही होस्ट पर कई ग्लिब्स स्थापित करना संभव है?

यह वह त्रुटि है जो मुझे तब मिलती है जब मैं पुराने ग्लिब पर अपना कार्यक्रम चलाता हूं:

./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)

तो ऐसा प्रतीत होता है कि वे अभी भी / परिवाद से जुड़ रहे हैं और नहीं उठा रहे हैं जहां से मैंने उन्हें डाल दिया है?

धन्यवाद


1
SLES-11 सर्वर के साथ भी यही समस्या है। अद्यतन नहीं कर सकते हैं और हाल के सामान की आवश्यकता है। ओह
माय

FWIW, मेरे लिए समस्या का समाधान export LD_LIBRARY_PATH=newglibc:$LD_LIBRARY_PATH किया ! यह निश्चित रूप से हर किसी के लिए काम नहीं करेगा, लेकिन अगर यह काम करता है तो यह एक आसान तय है! धन्यवाद! :)
रिनोगो

जवाबों:


229

एक ही सिस्टम पर ग्लिबक के कई संस्करण होना संभव है (हम हर दिन ऐसा करते हैं)।

हालांकि, आपको यह जानना होगा कि ग्लिबक में कई टुकड़े (200+ साझा लाइब्रेरी) होते हैं, जो सभी को मेल खाना चाहिए। टुकड़ों में से एक ld-linux.so.2 है, और यह libc.so.6 से मेल खाना चाहिए , या आप उन त्रुटियों को देखेंगे जिन्हें आप देख रहे हैं।

Ld-linux.so.2 का पूर्ण पथ लिंक समय पर निष्पादन योग्य में हार्ड-कोडित है, और लिंक किए जाने के बाद आसानी से नहीं बदला जा सकता है।

एक निष्पादन योग्य बनाने के लिए, जो नए ग्लिबक के साथ काम करेगा, ऐसा करें:

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एप्लिकेशन को रिंकल नहीं कर सकते हैं (जैसे कि यह तृतीय-पक्ष बाइनरी है), तो सभी खो नहीं जाता है, लेकिन यह मुश्किल हो जाता है। एक समाधान यह है कि chrootइसके लिए उचित वातावरण निर्धारित किया जाए। एक और संभावना rtldi और एक द्विआधारी संपादक का उपयोग करने के लिए है ।


3
ध्यान दें कि -Wl,--dynamic-linker=file(केवल दो '-' लेता है) केवल तब काम करता है जब ELF निष्पादक के लिए संकलन किया जाता है। चेक/sbin/ldconfig -p | grep ld
टॉम

49
अब आप एक सुविधाजनक उपयोगिता patchelf( nixos.org/patchelf.html ) का उपयोग कर सकते हैं , जो आपको पहले से संकलित ELF के rpath और दुभाषिया को संशोधित करने की अनुमति देता है।
माइकल पैंकोव

10
यह ध्यान देने योग्य है कि सुविधा के अलावा अन्य कारणों -Wl,--rpathसे नए ग्लिबक के लिए पथ निर्दिष्ट करना LD_LIBRARY_PATHमहत्वपूर्ण हो सकता है: यदि कार्यक्रम बाल प्रक्रियाओं को लॉन्च करता है, तो LD_LIBRARY_PATHआमतौर पर उनके द्वारा विरासत में मूल्य प्राप्त किया जाएगा, लेकिन यदि वे भी उपयोग करने के लिए संकलित नहीं हैं नए glibc (उदाहरण के लिए, यदि वे स्टॉक बायनेरी जैसे हैं bash), तो वे लॉन्च नहीं करेंगे।
HighCommander4

13
एक और विकल्प सीधे नया ld.so चला रहा है, इसे अपने द्विआधारी कार्यक्रम को एक पैरामीटर के रूप में पारित कर रहा है; यह प्रभावी रूप से ld.so का उपयोग करेगा w / o को कार्यक्रम को फिर से शुरू करने की आवश्यकता होगी:/path/to/newglibc/ld-linux.so.2 --library-path /path/tonewglibc/lib64:/path/to/newglibc/usr/lib64 /path/to/myapp
maximk

मुझे भी जरूरत थी -Iऔर -L: stackoverflow.com/a/52454603/895245
Ciro Santilli 病 stack stack stack

67

यह प्रश्न पुराना है, अन्य उत्तर पुराने हैं। "नियोजित रूसी" का उत्तर बहुत अच्छा और जानकारीपूर्ण है, लेकिन यह केवल तभी काम करता है जब आपके पास स्रोत कोड हो। यदि आप नहीं करते हैं, तो विकल्प बहुत मुश्किल थे। सौभाग्य से आजकल हमारे पास इस समस्या का एक सरल समाधान है (जैसा कि उनके एक उत्तर में टिप्पणी की गई है), patchelf का उपयोग करते हुए । तुमको बस यह करना है:

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

और उसके बाद, आप अपनी फ़ाइल को निष्पादित कर सकते हैं:

$ ./myapp

chrootधन्यवाद के लिए बायनेरिज़ को या मैन्युअल रूप से संपादित करने की आवश्यकता नहीं है । लेकिन अपने बाइनरी को पैच करने से पहले बैकअप लेना याद रखें, यदि आप सुनिश्चित नहीं हैं कि आप क्या कर रहे हैं, क्योंकि यह आपकी बाइनरी फ़ाइल को संशोधित करता है। आप इसे पैच करने के बाद, आप दुभाषिया / rpath के लिए पुराने पथ को पुनर्स्थापित नहीं कर सकते। यदि यह काम नहीं करता है, तो आपको इसे तब तक पैच करना होगा, जब तक कि आपको वह रास्ता न मिल जाए जो वास्तव में काम करेगा ... खैर, इसके लिए ट्रायल-एंड-एरर प्रोसेस होना जरूरी नहीं है। उदाहरण के लिए, ओपी के उदाहरण में, उसकी जरूरत थी 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

सिद्धांत रूप में, पहला grep खाली आएगा क्योंकि सिस्टम libc में वह संस्करण नहीं है जो वह चाहता है, और दूसरे को GLIBC_2.3 का उत्पादन करना चाहिए क्योंकि इसका संस्करण myappउपयोग कर रहा है, इसलिए हमें पता है कि हम patchelfउस पथ का उपयोग करके अपने बाइनरी को जान सकते हैं ।

जब आप लिनक्स में एक बाइनरी चलाने की कोशिश करते हैं, तो बाइनरी लिंकर को लोड करने की कोशिश करता है, फिर पुस्तकालयों, और वे सभी रास्ते में और / या सही जगह पर होना चाहिए। यदि आपकी समस्या लिंकर के साथ है और आप यह जानना चाहते हैं कि आपका बाइनरी किस रास्ते की तलाश कर रहा है, तो आप इस कमांड से पता कर सकते हैं:

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

यदि आपकी समस्या परिवादों के साथ है, तो आदेश जो आपको उपयोग किए जा रहे परिवाद देंगे:

$ readelf -d myapp | grep Shared
$ ldd myapp 

यह उन ब्योरों को सूचीबद्ध करेगा जिनकी बाइनरी की जरूरत है, लेकिन आप शायद पहले से ही समस्याग्रस्त लोगों को जानते हैं, क्योंकि वे पहले से ही ओपी के मामले में त्रुटियों की उपज दे रहे हैं।

"patchelf" कई अलग-अलग समस्याओं के लिए काम करता है, जिन्हें आप इन 2 समस्याओं से संबंधित प्रोग्राम चलाने की कोशिश करते समय सामना कर सकते हैं। उदाहरण के लिए, यदि आपको मिलता है: ELF file OS ABI invalidयह एक नया लोडर ( --set-interpreterकमांड का हिस्सा) सेट करके तय किया जा सकता है जैसा कि मैं यहां बताता हूं । एक अन्य उदाहरण यह है कि No such file or directoryजब आप किसी फ़ाइल को चलाते हैं, तो यह समस्या होती है और यहाँ निष्पादन योग्य होता है । उस विशेष मामले में, ओपी लोडर के लिए एक लिंक गायब था, लेकिन शायद आपके मामले में आपके पास रूट एक्सेस नहीं है और लिंक नहीं बना सकता है। एक नया दुभाषिया स्थापित करने से आपकी समस्या दूर हो जाएगी।

धन्यवाद अंतर्दृष्टि और समाधान के लिए रूसी और माइकल Pankov कार्यरत हैं!


1
यह सबसे मददगार था! मैं tensorflow के लिए नए glibc उपयोग करने के लिए अजगर द्विआधारी समझौता
faizan

यह एक साफ समाधान है (मुझे पहले से पता नहीं था patchelf), लेकिन वाक्यांश "कोई ज़रूरत नहीं है ... बायनेरी संपादित करें" थोड़ा भ्रामक हो सकता है (क्योंकि आप वास्तव में अपने बायनेरिज़ को संपादित कर रहे हैं)।
लार्क्स

वहाँ, तय किया। ;)
एमएसबी

वास्तव में उपयोगी उपयोगिता! धन्यवाद! यद्यपि मैं केवल मैन्युअल रूप से निर्भरता को हल करने के घंटों के बाद एक विभाजन दोष प्राप्त करने में कामयाब रहा, फिर बिना किसी व्यवस्थापक विशेषाधिकारों के साथ स्थानीय रूप से क्रोम स्थापित करने के लिए सब कुछ पैचिंग ...
जी। बर्जरन

@fgiraldeau को बधाई के लिए धन्यवाद। :) लेकिन सवाल पूछा गया, जवाब दिया गया और 2009 में स्वीकार कर लिया गया, मैं किसी को उत्तर देने से पहले 8 साल इंतजार करने की उम्मीद नहीं करूंगा। हेहेह; डी
एमएसबी

20

LD_PRELOAD का उपयोग करें: अपनी लाइब्रेरी को कहीं से भी आदमी के लिबास डायरेक्टरी से बाहर रखें और चलाएं:

LD_PRELOAD='mylibc.so anotherlib.so' program

देखें: विकिपीडिया लेख


1
यह एक जटिल Makefile के लिए एक अच्छा समाधान होगा, लेकिन यह मेरे लिए काम नहीं किया
galactica

यह विशेष रूप से उन लोगों के लिए उपयोगी है जिनका कोई स्रोत बाइनरी नहीं है। धन्यवाद
कोडर

2
उम ... मैं गलत था ,, ऐसा लगता है जैसे मुझे rdath की ज़रूरत है ld-linux.so / to / path / to / new / lib / frist जबकि source compile & linking
coder

1
यदि ld - # #। ## काम नहीं करता है, तो (आपके सिस्टम से glibc lib) libc.so. # (आपके वैकल्पिक glibc lib से) के समान समान संस्करण नहीं है
Andy

12

सबसे पहले, प्रत्येक गतिशील रूप से जुड़े कार्यक्रम की सबसे महत्वपूर्ण निर्भरता लिंकर है। सभी पुस्तकालयों को लिंकर के संस्करण से मेल खाना चाहिए।

आइए सरल निर्वासन लें: मेरे पास न्यूज़सेट ubuntu प्रणाली है जहां मैं कुछ प्रोग्राम चलाता हूं (मेरे मामले में यह डी कंपाइलर है - 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 से सेंटो तक सभी निर्भरता की प्रतिलिपि बनाना है। उचित विधि निम्नलिखित है:

सबसे पहले, सभी निर्भरता की जाँच करें:

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 लिंकर है, जिसका उपयोग लिनक्स द्वारा किया जाता है जो सभी गतिशील पुस्तकालयों के साथ निष्पादन योग्य को जोड़ता है।

बाकी फाइलें असली लाइब्रेरियां हैं और उन सभी को लिंकर के साथ सेंटोस में कहीं कॉपी किया जाना चाहिए।

मान लें कि सभी लाइब्रेरी और लिंकर "/ mylibs" डायरेक्टरी में हैं।

ld-linux-x86-64.so.2 - जैसा कि मैंने पहले ही कहा है - लिंकर है। यह गतिशील पुस्तकालय नहीं बल्कि स्थैतिक निष्पादन योग्य है। आप इसे चला सकते हैं और देख सकते हैं कि इसके कुछ पैरामीटर भी हैं, उदाहरण के लिए-library-path (मैं इसे वापस करूँगा)।

लिनक्स पर, डायनामिकली लिंक्ड प्रोग्राम को इसके नाम से ही लंच किया जा सकता है, जैसे

/bin/ldc2

लिनक्स ऐसे प्रोग्राम को RAM में लोड करता है, और जाँचता है कि इसके लिए कौन सा लिंकर सेट है। आमतौर पर, 64-बिट सिस्टम पर, यह /lib64/ld-linux-x86-64.so.2 है (आपके फाइल सिस्टम में यह वास्तविक निष्पादन योग्य का प्रतीकात्मक लिंक है)। फिर लिनक्स लिंकर चलाता है और यह गतिशील पुस्तकालयों को लोड करता है।

आप इसे थोड़ा बदल सकते हैं और इस तरह की चाल कर सकते हैं:

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

यह लाइनर को विशिष्ट लिंकर का उपयोग करने के लिए मजबूर करने की विधि है।

और अब हम उल्लिखित पूर्व पैरामीटर --library-path पर लौट सकते हैं

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

यह ldc2 चलाएगा और / mylibs से डायनामिक लाइब्रेरी लोड करेगा।

यह चयन योग्य (सिस्टम डिफॉल्ट नहीं) पुस्तकालयों के साथ निष्पादन योग्य कॉल करने की विधि है।


मैंने आरएच 7 पर एक कार्यक्रम संकलित किया और इसे आरएच 6 पर चलाने की आवश्यकता है। मैं एक नया निष्पादन योग्य बनाना या patchelf का उपयोग नहीं करना चाहता था, इसलिए यह एक बढ़िया विकल्प है।
मार्क राजकोक

9

सेटअप 1: समर्पित जीसीसी के बिना अपने स्वयं के ग्लिब को संकलित करें और इसका उपयोग करें

यह सेटअप काम कर सकता है और यह त्वरित है क्योंकि यह पूरे जीसीसी टूलकिन को फिर से स्थापित नहीं करता है, बस ग्लिबक।

लेकिन यह विश्वसनीय के रूप में यह का उपयोग करता है मेजबान सी क्रम इस तरह की वस्तुओं के रूप में नहीं है crt1.o, crti.oऔर crtn.oglibc द्वारा प्रदान की। इसका उल्लेख यहां किया गया है: https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_cocation उन वस्तुओं को जल्दी सेटअप करते हैं जो ग्लिबक पर भरोसा करते हैं, इसलिए मुझे आश्चर्य नहीं होगा कि चीजें आश्चर्यजनक रूप से दुर्घटनाग्रस्त हो गईं। और भयानक सूक्ष्म तरीके।

अधिक विश्वसनीय सेटअप के लिए, नीचे सेटअप 2 देखें।

ग्लिबक बनाएँ और स्थानीय रूप से स्थापित करें:

export glibc_install="$(pwd)/glibc/build/install"

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28
mkdir build
cd build
../configure --prefix "$glibc_install"
make -j `nproc`
make install -j `nproc`

सेटअप 1: बिल्ड को सत्यापित करें

test_glibc.c

#define _GNU_SOURCE
#include <assert.h>
#include <gnu/libc-version.h>
#include <stdatomic.h>
#include <stdio.h>
#include <threads.h>

atomic_int acnt;
int cnt;

int f(void* thr_data) {
    for(int n = 0; n < 1000; ++n) {
        ++cnt;
        ++acnt;
    }
    return 0;
}

int main(int argc, char **argv) {
    /* Basic library version check. */
    printf("gnu_get_libc_version() = %s\n", gnu_get_libc_version());

    /* Exercise thrd_create from -pthread,
     * which is not present in glibc 2.27 in Ubuntu 18.04.
     * /programming/56810/how-do-i-start-threads-in-plain-c/52453291#52453291 */
    thrd_t thr[10];
    for(int n = 0; n < 10; ++n)
        thrd_create(&thr[n], f, NULL);
    for(int n = 0; n < 10; ++n)
        thrd_join(thr[n], NULL);
    printf("The atomic counter is %u\n", acnt);
    printf("The non-atomic counter is %u\n", cnt);
}

संकलित करें और चलाएं test_glibc.sh:

#!/usr/bin/env bash
set -eux
gcc \
  -L "${glibc_install}/lib" \
  -I "${glibc_install}/include" \
  -Wl,--rpath="${glibc_install}/lib" \
  -Wl,--dynamic-linker="${glibc_install}/lib/ld-linux-x86-64.so.2" \
  -std=c11 \
  -o test_glibc.out \
  -v \
  test_glibc.c \
  -pthread \
;
ldd ./test_glibc.out
./test_glibc.out

कार्यक्रम अपेक्षित परिणाम देता है:

gnu_get_libc_version() = 2.28
The atomic counter is 10000
The non-atomic counter is 8674

कमांड https://sourceware.org/glibc/wiki/Testing/Builds?action=recall&rev=21#Compile_against_glibc_in_an_installed_live से अनुकूलित किया गया, लेकिन --sysrootइसके साथ विफल रहा:

cannot find /home/ciro/glibc/build/install/lib/libc.so.6 inside /home/ciro/glibc/build/install

इसलिए मैंने इसे हटा दिया।

lddआउटपुट पुष्टि करता है lddकि हमारे द्वारा अभी-अभी बनाए गए पुस्तकालयों को वास्तव में अपेक्षित रूप से उपयोग किया जा रहा है:

+ ldd test_glibc.out
        linux-vdso.so.1 (0x00007ffe4bfd3000)
        libpthread.so.0 => /home/ciro/glibc/build/install/lib/libpthread.so.0 (0x00007fc12ed92000)
        libc.so.6 => /home/ciro/glibc/build/install/lib/libc.so.6 (0x00007fc12e9dc000)
        /home/ciro/glibc/build/install/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007fc12f1b3000)

gccसंकलन डिबग आउटपुट शो है कि मेरे मेजबान क्रम वस्तुओं का उपयोग किया गया है, जो बुरा जैसा कि पहले उल्लेख है, लेकिन मैं यह कैसे हल करने के लिए पता नहीं है के रूप में है, जैसे यह शामिल हैं:

COLLECT_GCC_OPTIONS=/usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/crt1.o

सेटअप 1: glibc संशोधित करें

अब आइए ग्लिबक को संशोधित करें:

diff --git a/nptl/thrd_create.c b/nptl/thrd_create.c
index 113ba0d93e..b00f088abb 100644
--- a/nptl/thrd_create.c
+++ b/nptl/thrd_create.c
@@ -16,11 +16,14 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */

+#include <stdio.h>
+
 #include "thrd_priv.h"

 int
 thrd_create (thrd_t *thr, thrd_start_t func, void *arg)
 {
+  puts("hacked");
   _Static_assert (sizeof (thr) == sizeof (pthread_t),
                   "sizeof (thr) != sizeof (pthread_t)");

फिर recompile और फिर से स्थापित glibc, और recompile और हमारे प्रोग्राम को फिर से चलाएँ:

cd glibc/build
make -j `nproc`
make -j `nproc` install
./test_glibc.sh

और हम hackedउम्मीद के मुताबिक कई बार छपे हुए देखते हैं ।

यह आगे पुष्टि करता है कि हमने वास्तव में उस glibc का उपयोग किया था जिसे हमने संकलित किया था और मेजबान को नहीं।

उबुन्टु 18.04 पर परीक्षण किया गया।

सेटअप 2: क्रॉसस्टूल-एनजी प्राचीन सेटअप

इस सेटअप 1 के लिए एक विकल्प है, और यह सबसे सही सेटअप मैं अब तक हासिल कर लिया है है: सब कुछ जहाँ तक सही है के रूप में मैं भी शामिल सी क्रम जैसे वस्तुओं, का निरीक्षण कर सकते crt1.o, crti.o, और crtn.o

इस सेटअप में, हम एक पूर्ण समर्पित जीसीसी टूलकिन संकलित करेंगे जो कि हम चाहते हैं कि glibc का उपयोग करता है।

इस पद्धति का एकमात्र नकारात्मक पहलू यह है कि निर्माण में अधिक समय लगेगा। लेकिन मैं कुछ भी कम के साथ एक उत्पादन सेटअप जोखिम नहीं होगा।

crosstool-NG स्क्रिप्ट्स का एक सेट है जो GCC, glibc और bincils सहित हमारे लिए स्रोत से सब कुछ डाउनलोड और संकलित करता है।

हां जीसीसी बिल्ड सिस्टम इतना खराब है कि हमें इसके लिए एक अलग प्रोजेक्ट की जरूरत है।

यह सेटअप केवल सही नहीं है क्योंकि क्रॉस्टूल-एनजी अतिरिक्त -Wlझंडे के बिना निष्पादन के निर्माण का समर्थन नहीं करता है , जो अजीब लगता है क्योंकि हमने स्वयं एनसीसी का निर्माण किया है। लेकिन सब कुछ काम करने लगता है, इसलिए यह केवल एक असुविधा है।

क्रोसस्टूल-एनजी प्राप्त करें, इसे कॉन्फ़िगर करें और इसका निर्माण करें:

git clone https://github.com/crosstool-ng/crosstool-ng
cd crosstool-ng
git checkout a6580b8e8b55345a5a342b5bd96e42c83e640ac5
export CT_PREFIX="$(pwd)/.build/install"
export PATH="/usr/lib/ccache:${PATH}"
./bootstrap
./configure --enable-local
make -j `nproc`
./ct-ng x86_64-unknown-linux-gnu
./ct-ng menuconfig
env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

बिल्ड में लगभग तीस मिनट से दो घंटे लगते हैं।

एकमात्र अनिवार्य कॉन्फ़िगरेशन विकल्प जो मैं देख सकता हूं, यह सही कर्नेल हेडर का उपयोग करने के लिए आपके होस्ट कर्नेल संस्करण से मेल खा रहा है। इसके साथ अपना होस्ट कर्नेल संस्करण खोजें:

uname -a

जो मुझे दिखाता है:

4.15.0-34-generic

तो menuconfigमैं करता हूँ:

  • Operating System
    • Version of linux

इसलिए मैं चयन करता हूं:

4.14.71

जो पहला समान या पुराना संस्करण है। यह पुराने होने के बाद से कर्नेल पीछे संगत है।

सेटअप 2: वैकल्पिक कॉन्फ़िगरेशन

इसके .configसाथ हमने जो उत्पन्न किया ./ct-ng x86_64-unknown-linux-gnuहै:

CT_GLIBC_V_2_27=y

यह करने के लिए, कि menuconfig:

  • C-library
  • Version of glibc

सहेजें .config, और बिल्ड के साथ जारी रखें।

या, यदि आप अपने स्वयं के ग्लिबक स्रोत का उपयोग करना चाहते हैं, उदाहरण के लिए नवीनतम गिट से ग्लिबक का उपयोग करना चाहते हैं, तो इस तरह से आगे बढ़ें :

  • Paths and misc options
    • Try features marked as EXPERIMENTAL: सच में सेट
  • C-library
    • Source of glibc
      • Custom location: हाँ बोलो
      • Custom location
        • Custom source location: अपने glibc स्रोत वाली निर्देशिका की ओर इंगित करें

जहां ग्लिबक को क्लोन किया गया था:

git clone git://sourceware.org/git/glibc.git
cd glibc
git checkout glibc-2.28

सेटअप 2: इसका परीक्षण करें

एक बार जब आप वह चाहते हैं कि आप चाहते हैं, तो इसे बाहर का परीक्षण करें:

#!/usr/bin/env bash
set -eux
install_dir="${CT_PREFIX}/x86_64-unknown-linux-gnu"
PATH="${PATH}:${install_dir}/bin" \
  x86_64-unknown-linux-gnu-gcc \
  -Wl,--dynamic-linker="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2" \
  -Wl,--rpath="${install_dir}/x86_64-unknown-linux-gnu/sysroot/lib" \
  -v \
  -o test_glibc.out \
  test_glibc.c \
  -pthread \
;
ldd test_glibc.out
./test_glibc.out

सब कुछ सेटअप 1 के रूप में काम करने लगता है, सिवाय इसके कि अब सही रनटाइम ऑब्जेक्ट का उपयोग किया गया था:

COLLECT_GCC_OPTIONS=/home/ciro/crosstool-ng/.build/install/x86_64-unknown-linux-gnu/bin/../x86_64-unknown-linux-gnu/sysroot/usr/lib/../lib64/crt1.o

सेटअप 2: विफल कुशल glibc पुनर्संयोजन का प्रयास

यह क्रॉस्टूल-एनजी के साथ संभव नहीं लगता है, जैसा कि नीचे बताया गया है।

यदि आप बस फिर से निर्माण करते हैं;

env -u LD_LIBRARY_PATH time ./ct-ng build CT_JOBS=`nproc`

तब कस्टम ग्लिबक स्रोत स्थान में आपके बदलावों को ध्यान में रखा जाता है, लेकिन यह खरोंच से सब कुछ बनाता है, जिससे पुनरावृत्ति विकास के लिए यह बेकार हो जाता है।

यदि हम करें तो:

./ct-ng list-steps

यह बिल्ड चरणों का एक अच्छा अवलोकन देता है:

Available build steps, in order:
  - companion_tools_for_build
  - companion_libs_for_build
  - binutils_for_build
  - companion_tools_for_host
  - companion_libs_for_host
  - binutils_for_host
  - cc_core_pass_1
  - kernel_headers
  - libc_start_files
  - cc_core_pass_2
  - libc
  - cc_for_build
  - cc_for_host
  - libc_post_cc
  - companion_libs_for_target
  - binutils_for_target
  - debug
  - test_suite
  - finish
Use "<step>" as action to execute only that step.
Use "+<step>" as action to execute up to that step.
Use "<step>+" as action to execute from that step onward.

इसलिए, हम देखते हैं कि कई GCC चरणों के साथ interibined glibc चरण हैं, सबसे विशेष रूप libc_start_filesसे पहले आता है cc_core_pass_2, जो संभवतः एक साथ सबसे महंगा कदम है cc_core_pass_1

केवल एक कदम बनाने के लिए, आपको पहले " .configबिल्ड इंटरमीडिएट स्टेप्स" को इंटिअल बिल्ड के लिए विकल्प में सेट करना होगा :

  • Paths and misc options
    • Debug crosstool-NG
      • Save intermediate steps

और फिर आप कोशिश कर सकते हैं:

env -u LD_LIBRARY_PATH time ./ct-ng libc+ -j`nproc`

लेकिन दुर्भाग्य से, के +रूप में आवश्यक उल्लेख: https://github.com/crosstool-ng/crosstool-ng/issues/1033#issuecomment-424877536

हालाँकि, ध्यान दें कि एक मध्यवर्ती चरण पर पुनरारंभ करने से उस चरण के दौरान राज्य में स्थापना निर्देशिका रीसेट हो जाती है। यानी, आपके पास एक पुनर्निर्माण लिबेक होगा - लेकिन कोई भी अंतिम संकलक इस परिवाद के साथ नहीं बनाया गया है (और इसलिए, कोई संकलक लाइब्रेरी जैसे libstdc ++ या तो नहीं)।

और मूल रूप से अभी भी पुनर्निर्माण को बहुत धीमी गति से विकास के लिए संभव बनाता है, और मैं यह नहीं देखता कि क्रॉस्टूल-एनजी को पैच किए बिना इसे कैसे पार किया जाए।

इसके अलावा, libcकदम से शुरू करने से स्रोत पर फिर से प्रतिलिपि नहीं लगती थी Custom source location, आगे इस पद्धति को अनुपयोगी बना दिया।

बोनस: stdlibc ++

एक बोनस यदि आप C ++ मानक पुस्तकालय में रुचि रखते हैं: GCC libstdc ++ C ++ लाइब्रेरी लाइब्रेरी स्रोत को कैसे संपादित करें और फिर से बनाएं?


6

क्या आप निक्स http://nixos.org/nix/ का उपयोग करने पर विचार कर सकते हैं ?

निक्स बहु-उपयोगकर्ता पैकेज प्रबंधन का समर्थन करता है: कई उपयोगकर्ता सुरक्षित रूप से एक आम निक्स स्टोर साझा कर सकते हैं, सॉफ़्टवेयर स्थापित करने के लिए रूट विशेषाधिकार होने की आवश्यकता नहीं है, और पैकेज के विभिन्न संस्करणों को स्थापित और उपयोग कर सकते हैं।


4

@msb एक सुरक्षित समाधान देता है।

मुझे यह समस्या तब हुई जब मैंने import tensorflow as tfकोंडा वातावरण में CentOS 6.5किया , जिसमें केवल है glibc-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 स्थापित करने के लिए उसी तरह का पालन करें ;

तीसरा, अपने पायथन को पैच करें:

[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/


2

मुझे यकीन नहीं है कि सवाल अभी भी प्रासंगिक है, लेकिन समस्या को ठीक करने का एक और तरीका है: डॉकटर। स्रोत वितरण का लगभग खाली कंटेनर स्थापित कर सकते हैं (विकास के लिए उपयोग किया गया वितरण) और कंटेनर में फ़ाइलों की प्रतिलिपि बनाएँ। इस तरह आपको चिरोट के लिए आवश्यक फाइल सिस्टम बनाने की आवश्यकता नहीं है।


1

यदि आप दूसरे आउटपुट को करीब से देखते हैं तो आप देख सकते हैं कि पुस्तकालयों के लिए नए स्थान का उपयोग किया जाता है। शायद वहाँ अभी भी लापता पुस्तकालय हैं जो ग्लिबक का हिस्सा हैं।

मुझे यह भी लगता है कि आपके प्रोग्राम द्वारा उपयोग किए जाने वाले सभी पुस्तकालयों को ग्लिबक के उस संस्करण के खिलाफ संकलित किया जाना चाहिए। यदि आपके पास कार्यक्रम के स्रोत कोड तक पहुंच है, तो एक ताजा संकलन सबसे अच्छा समाधान प्रतीत होता है।


1

"कार्यरत रूसी" सबसे अच्छे उत्तर में से एक है, और मुझे लगता है कि अन्य सभी सुझाए गए उत्तर काम नहीं कर सकते हैं। इसका कारण सिर्फ यह है कि जब कोई एप्लिकेशन पहली बार बनाई जाती है, तो उसके सभी एपीआई की जरूरत होती है। "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)

लेकिन रनटाइम के दौरान, फ़ायरफ़ॉक्स कई अन्य गतिशील पुस्तकालयों को भी लोड करेगा, उदाहरण के लिए (फ़ायरफ़ॉक्स के लिए) बहुत सारे "ग्लिब" -लॉबल्ड लाइब्रेरीज़ लोड किए गए हैं (भले ही वैधानिक रूप से जुड़े हुए हैं कोई नहीं):

 /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

इसलिए इसका अर्थ है कि "पुस्तकालयों" के विभिन्न संस्करण एक प्रणाली में मौजूद हैं - जो एक समस्या नहीं है क्योंकि यह एक ही फ़ाइल है, और यह कई अनुप्रयोगों पर निर्भरता होने पर संगतता प्रदान करेगा।

इसलिए, सिस्टम स्तर पर, सभी लाइब्रेरी लगभग एक दूसरे पर निर्भर होती हैं, और केवल LD_PRELOAD या LD_LIBRARY_PATH में हेरफेर करके लाइब्रेरी लोडिंग प्राथमिकता को बदलने में मदद नहीं करेगा - यहां तक ​​कि यह लोड हो सकता है, रनटाइम यह अभी भी क्रैश हो सकता है।

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

सबसे अच्छा विकल्प चिरोट (ईआर द्वारा संक्षेप में उल्लिखित) है: लेकिन इसके लिए आपको पूरे वातावरण को फिर से बनाना होगा जिसमें मूल बाइनरी निष्पादन है - आमतौर पर / lib, / usr / lib /, usr / lib / x86 आदि से शुरू होता है। आप या तो "Buildroot", या YoctoProject का उपयोग कर सकते हैं, या केवल एक मौजूदा Distro वातावरण से टार कर सकते हैं। (जैसे फेडोरा / स्यूस आदि)।


0

जब मैं उबंटू सटीक (glibc-2.15) पर क्रोमियम-ब्राउज़र चलाना चाहता था, तो मुझे "(विशिष्ट) संदेश" ... libc.so.6: संस्करण 'GLIBC_2.19' नहीं मिला ... "मिला। मैंने इस तथ्य पर विचार किया, कि फाइलों को अनुमति की जरूरत नहीं है, लेकिन केवल शुरुआत के लिए। इसलिए मैंने ब्राउज़र और सुडो के लिए आवश्यक फ़ाइलों को एकत्र किया और एक मिनी-ग्लिब-2.19- वातावरण बनाया, ब्राउज़र को शुरू किया और फिर मूल फ़ाइलों को फिर से कॉपी किया। आवश्यक फाइलें रैम में हैं और मूल ग्लिबक समान है।

as root
the files (*-2.15.so) already exist 

mkdir -p /glibc-2.19/i386-linux-gnu

/glibc-2.19/ld-linux.so.2 -> /glibc-2.19/i386-linux-gnu/ld-2.19.so
/glibc-2.19/i386-linux-gnu/libc.so.6 -> libc-2.19.so
/glibc-2.19/i386-linux-gnu/libdl.so.2 -> libdl-2.19.so
/glibc-2.19/i386-linux-gnu/libpthread.so.0 -> libpthread-2.19.so

mkdir -p /glibc-2.15/i386-linux-gnu

/glibc-2.15/ld-linux.so.2 -> (/glibc-2.15/i386-linux-gnu/ld-2.15.so)
/glibc-2.15/i386-linux-gnu/libc.so.6 -> (libc-2.15.so)
/glibc-2.15/i386-linux-gnu/libdl.so.2 -> (libdl-2.15.so)
/glibc-2.15/i386-linux-gnu/libpthread.so.0 -> (libpthread-2.15.so)

ब्राउज़र चलाने के लिए स्क्रिप्ट:

#!/bin/sh
sudo cp -r /glibc-2.19/* /lib
/path/to/the/browser &
sleep 1
sudo cp -r /glibc-2.15/* /lib
sudo rm -r /lib/i386-linux-gnu/*-2.19.so
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.