如何使Unix二进制独立?

我有一个没有源代码的Linux二进制文件,可以在一台机器上运行,我想制作一个独立的软件包,它可以在同一架构的不同机器上运行。 什么是实现这个方法?

在我的情况下,两台机器具有相同的体系结构,相同的Ubuntu内核,但是目标机器没有make并且在/lib/usr下有错误的文件版本

我有一个想法是使用chroot并重新创build二进制文件系统的一个子集,可能使用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解决scheme的问题在于/lib被硬编码到解释器中,并且优先于LD_LIBRARY_PATH ,所以本地版本将首先被加载。 解释器被硬编码到二进制文件中。 一种方法可能是修补解释器并以patched_interpreter mycommandline运行二进制文件问题在于,当mycommandlinejava开头时,这不起作用,因为Java设置了LD_LIBRARY_PATH并重新启动自身,并使用旧的解释器。 对我来说,一个解决scheme是在文本编辑器中打开二进制文件,find解释器( /lib/ld-linux-x86-64.so.2 ),并用相同长度的pathreplace为解释器

Solutions Collecting From Web of "如何使Unix二进制独立?"

有CDE的一些软件设计来做你想要的。 这是一个关于它的谷歌技术讨论http://www.youtube.com/watch?v=6XdwHo1BWwY

正如其他人所说,静态链接是一种选择。 除了与glibc的静态链接,每一个版本都会有一些破裂(对不起,没有参考,只是我的经验)。

你的chroot想法可能是矫枉过正的。

据我所知,大多数商业产品使用的解决方案是将其“应用程序”设置为设置LD_LIBRARY_PATH的shell脚本,然后运行实际的可执行文件。 沿着这些线路的东西:

 #!/bin/sh here=`dirname "$0"` export LD_LIBRARY_PATH="$here"/lib exec "$here"/bin/my_app "$@" 

然后你只需要在lib/下面转储所有相关的.so文件的副本,把你的可执行文件放在bin/ ,把脚本放在里面. ,然后运送整棵树。

(为了生产,如果非空的话,正确地在"$here"/lib加上LD_LIBRARY_PATH ,等等)

[编辑,去更新]

我想你可能会困惑什么是硬编码的,什么不是。 ld-linux-x86-64.so.2是动态链接器本身; 而且您的路径是硬编码到ELF标头中是正确的。 但其他库不是硬编码的; 他们被动态链接器搜索,这将履行LD_LIBRARY_PATH

如果你真的需要一个不同的ld-linux.so,那么只需要运行动态链接器本身而不是修改ELF头文件:

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

这将使用您的链接器而不是ELF标题中列出的链接器。

修补可执行文件本身是邪恶的。 请考虑一下在你继续前进之后必须维护你的东西的那个可怜的人。 没有人会指望你手动破解ELF头。 任何人都可以阅读一个shell脚本正在做什么。

只是我的$ 0.02。

几乎肯定会有更好的答案,但是你可以通过ldd命令(例如ls二进制)找出二进制文件需要的库:

 $ 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) 

一旦你有这个,你可以复制,并把它们放在目标机器上的适当位置。