2011-07-15 14 views
10

मेरे पास एक लिनक्स बाइनरी है, स्रोतों के बिना, जो एक मशीन पर काम करता है, और मैं एक स्व-निहित पैकेज बनाना चाहता हूं जो एक ही वास्तुकला की एक अलग मशीन पर चलती है। इसे प्राप्त करने का एक तरीका क्या है?यूनिक्स बाइनरी स्वयं निहित कैसे करें?

मेरे मामले में, दोनों मशीनों एक ही वास्तुकला, एक ही उबंटू गिरी है, लेकिन लक्ष्य मशीन make नहीं है और नीचे /lib और /usr

एक विचार मैं था फ़ाइलों के गलत संस्करण है chroot का इस्तेमाल किया गया और फाइल सिस्टम के सबसेट को फिर से बनाएं, जो कि बाइनरी का उपयोग करता है, संभवतः strace का उपयोग करके इसकी आवश्यकता होती है। क्या कोई ऐसा उपकरण है जो पहले से ही करता है?

भावी पीढ़ी के लिए, यहाँ है कि कैसे मैं यह पता लगाने की जो फाइल एक प्रक्रिया खोलता है

#!/usr/bin/python 
# source of trace_fileopen.py 
# Runs command and prints all files that have been successfully opened with mode O_RDONLY 
# example: trace_fileopen.py ls -l 
import re, sys, subprocess, os 

if __name__=='__main__': 
    strace_fn = '/tmp/strace.out' 
    strace_re = re.compile(r'([^(]+?)\((.*)\)\s*=\s*(\S+?)\s+(.*)$') 

    cmd = sys.argv[1] 
    nowhere = open('/dev/null','w')# 
    p = subprocess.Popen(['strace','-o', strace_fn]+sys.argv[1:], stdout=nowhere, stderr=nowhere) 
    sts = os.waitpid(p.pid, 0)[1] 

    output = [] 
    for line in open(strace_fn): 
    # ignore lines like --- SIGCHLD (Child exited) @ 0 (0) --- 
    if not strace_re.match(line): 
     continue 
    (function,args,returnval,msg) = strace_re.findall(line)[0] 
    if function=='open' and returnval!='-1': 
     (fname,mode)=args.split(',',1) 
     if mode.strip()=='O_RDONLY': 
     if fname.startswith('"') and fname.endswith('"') and len(fname)>=2: 
      fname = fname[1:-1] 
     output.append(fname) 
    prev_line = "" 
    for line in sorted(output): 
    if line==prev_line: 
     continue 
    print line 
    prev_line = line 

अद्यतन LD_LIBRARY_PATH समाधान के साथ समस्या यह है कि /lib दुभाषिया में hardcoded और LD_LIBRARY_PATH पर पूर्वता लेता है, इसलिए देशी संस्करण जाएगा पहले लोड हो जाओ। दुभाषिया बाइनरी में हार्डकोड किया गया है। एक दृष्टिकोण दुभाषिया को पैच करना और patched_interpreter mycommandline के रूप में द्विआधारी चलाने के लिए हो सकता है समस्या यह है कि mycommandlinejava के साथ शुरू होता है, यह काम नहीं करता है क्योंकि जावा सेट-अप LD_LIBRARY_PATH और पुराने दुभाषिया के लिए रिसॉर्ट करता है। मेरे लिए काम करने वाला एक समाधान टेक्स्ट एडिटर में बाइनरी खोलना था, दुभाषिया (/lib/ld-linux-x86-64.so.2) ढूंढें, और इसे पैच किए गए दुभाषिया

+4

लगता है जैसे आप एक स्थिर बाइनरी चाहते हैं। यह सभी पुस्तकालयों में बनाता है जो इसका उपयोग करता है। –

+0

क्या @ वीएलसी ने कहा, आपको इसे स्थिर लिंकिंग के लिए चिह्नित करना होगा, हालांकि यह दर्द का थोड़ा सा हो सकता है। –

+0

क्या आपने सवाल में बाइनरी बनाई थी? यदि आपने किया है, तो आप इसे स्थिर रूप से पुनर्निर्माण करने में सक्षम हो सकते हैं। – Cascabel

उत्तर

2

CDE कुछ ऐसा सॉफ़्टवेयर है जो आप चाहते हैं कि वास्तव में करने के लिए डिज़ाइन किया गया हो। इसके बारे में एक Google तकनीक की बात है http://www.youtube.com/watch?v=6XdwHo1BWwY

2

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

$ ldd /bin/ls 
linux-vdso.so.1 => (0x00007ffffff18000) 
librt.so.1 => /lib/librt.so.1 (0x00007f5ae565c000) 
libselinux.so.1 => /lib/libselinux.so.1 (0x00007f5ae543e000) 
libacl.so.1 => /lib/libacl.so.1 (0x00007f5ae5235000) 
libc.so.6 => /lib/libc.so.6 (0x00007f5ae4eb2000) 
libpthread.so.0 => /lib/libpthread.so.0 (0x00007f5ae4c95000) 
/lib64/ld-linux-x86-64.so.2 (0x00007f5ae588b000) 
libdl.so.2 => /lib/libdl.so.2 (0x00007f5ae4a90000) 
libattr.so.1 => /lib/libattr.so.1 (0x00007f5ae488b000) 

बार जब आप इस है, तो आप प्रतियां बनाने और उन्हें लक्षित मशीन पर उचित स्थानों में डाल सकता है।

+0

वास्तव में मैंने ऐसा कुछ किया है ('ldd' द्वारा रिपोर्ट नहीं की गई अतिरिक्त आवश्यक लाइब्रेरी ढूंढने के लिए' स्ट्रेस' का उपयोग करके), लेकिन मुझे संभावित रूप से मेरे प्रोग्राम का विचार पसंद नहीं है '~' के बाहर की चीजों के कारण तोड़ना जिन पर मेरा नियंत्रण नहीं है। 'chroot' अच्छा लग रहा है, लेकिन फाइल सिस्टम –

4

जैसा कि अन्य ने उल्लेख किया है, स्थैतिक लिंकिंग एक विकल्प है। ग्लिब के साथ स्थैतिक लिंक को छोड़कर प्रत्येक रिलीज के साथ थोड़ा और टूटा हो जाता है (क्षमा करें, कोई संदर्भ नहीं; बस मेरा अनुभव)।

आपका chroot विचार शायद अधिक है।

जहां तक ​​मैं कह सकता हूं, सबसे अधिक वाणिज्यिक उत्पादों का समाधान, उनके "एप्लिकेशन" को एक शेल स्क्रिप्ट बनाना है जो LD_LIBRARY_PATH सेट करता है और फिर वास्तविक निष्पादन योग्य चलाता है। इन पंक्तियों के साथ कुछ:

#!/bin/sh 
here=`dirname "$0"` 
export LD_LIBRARY_PATH="$here"/lib 
exec "$here"/bin/my_app "[email protected]" 

तो फिर तुम सिर्फ lib/ अंतर्गत फ़ाइलें .so सभी प्रासंगिक की एक प्रति डंप, bin/ के तहत अपने निष्पादन योग्य शब्दों में कहें, . में स्क्रिप्ट डाल दिया, और पूरे पेड़ जहाज।

(उत्पादन-योग्य होने के लिए, ठीक से LD_LIBRARY_PATH को "$here"/lib पहले जोड़ें अगर यह गैर खाली है, आदि)

[संपादित करें, आपकी नई जानकारी के साथ जाने के]

मुझे लगता है कि आप के बारे में उलझन में हो सकता है कड़ी मेहनत क्या है और क्या नहीं है। ld-linux-x86-64.so.2 डायनामिक लिंकर ही है; और आप सही हैं कि इसका पथ ईएलएफ हेडर में हार्ड-कोड किया गया है।लेकिन अन्य पुस्तकालयों को कड़ी-कोडित नहीं किया जाता है; वे गतिशील लिंकर द्वारा खोजे जाते हैं, जो LD_LIBRARY_PATH का सम्मान करेंगे।

तुम सच बजाय ELF हैडर पैचिंग की, एक अलग ld-linux.so की जरूरत है, बस गतिशील लिंकर ही चलाएँ:

/path/to/my-ld-linux.so my_program <args> 

यह बजाय ELF में डाला गया के अपने लिंकर का उपयोग करेगा हैडर।

निष्पादन योग्य खुद को पैच करना बुरा है। कृपया उस गरीब व्यक्ति पर विचार करें जिस पर आप आगे बढ़ने के बाद अपनी सामग्री को बनाए रखना चाहते हैं ... कोई भी आपको उम्मीद है कि आप हाथ से ईएलएफ शीर्षलेख हैक कर चुके हैं। कोई भी पढ़ सकता है कि एक शेल स्क्रिप्ट क्या कर रही है।

बस मेरा $ 0.02।

+0

का पुनर्निर्माण कैसे करें यह जानने के लिए यह काम करेगा कि समस्या यह है कि' ld_LIBRARY_PATH' में चीजों से पहले 'lib' में चीजें लोड हो जाएंगी। मैं 'chroot' का उपयोग किए बिना इसके आसपास मिला, अद्यतन प्रश्न निकाय –

+0

@ यरोस्लाव: वहां गया, ऐसा किया गया ... ध्यान दें कि आप बाइनरी को "/lib/my-ld-linux.so " के रूप में भी चला सकते हैं। जब आप ऐसा करते हैं, तो 'my-ld-linux.so' ईएलएफ शीर्षलेख में संस्करण को अनदेखा कर देगा। निष्पादन योग्य में ईएलएफ शीर्षलेख को पैच करने के बजाय यह किसी भी स्क्रिप्ट से आपके निष्पादन योग्य चलाने के लिए तर्कसंगत क्लीनर है (इसलिए कोई भी यह देख सकता है कि आप क्या कर रहे हैं) (जिसे कोई भी कभी नहीं समझ पाएगा)। – Nemo

+0

हाँ, आप वास्तव में वैकल्पिक सेवा होस्टनाम रिज़ॉल्यूशन को शामिल करने की अनुमति देने के लिए नाम सेवा स्विच तंत्र के कारण ग्लिब के साथ पूरी तरह से स्थिर लिंक नहीं कर सकते हैं। – Spudd86

संबंधित मुद्दे