如何在单个可执行文件中构建具有多个 Linux 实用程序的软件?
How build a software with mutliple Linux utilities in a single executable file?
我目前正在开发一个新项目,一个必须包含许多 Unix 实用程序(如 Busybox)的二进制文件。
例如,我希望能够像这样在我的工具箱中使用 netcat(具有静态依赖项):
./mytoolbox netcat
但是我不知道怎么执行。
此应用的哪种架构最好?
感谢您的帮助。
一种可能的方法是将符号链接指向您的可执行文件。因此,首先将 mytoolbox
executable file (in elf(5) format) and add symlinks (see ln(1), symlink(2), symlink(7), inode(7), credentials(7)...) like ln -s mytoolbox mytoolchain
. Then the file mytoolchain
is a symbolic link 构建为可执行文件 mytoolbox
.
然后,启动您的 main
函数:
int main(int argc, char**argv) {
if (!strcmp(argv[0], "mytoolbox"))
run_prog_my_toolbox(argc, argv);
else if (!strcmp(argv[0], "mytoolchain"))
run_prog_my_toolchain(argc, argv);
另一种可能性是使用 dlopen(3) and dlsym(3).
加载插件
您的 mytoolbox
可执行文件可能有依赖项。参见 execve(2), ldd(1), readelf(1)
例如,查看 GNU bash, which behaves differently when started as bash
or as rbash
(it then becomes a restricted shell) 的源代码。
考虑使用 GNU guile, Lua, or or code generating libraries such as libgccjit.
这样的解释器
注意 software licensing 问题。如果您重新分发可执行文件,LGPLv3 可能是相关的(对于 libc.so.6
)
有几种方法可以做到这一点:
要求系统中存在这些工具。从开发人员的角度来看,这是迄今为止最简单的选择,但也有一些缺点。它不太安全(你调用的是什么版本?)并且你需要处理命令版本之间的各种差异。
不要再认为您需要一个二进制文件。没有严肃的应用程序甚至会考虑这一点,因为一旦它达到任何合适的大小,link 时间就不值得了。只需将您想要的实用程序与您的应用程序一起发送并直接调用它们。
将应用程序嵌入到您的启动程序中 script/binary。将数据嵌入“脚本”的一个例子是 NVIDIA 驱动程序安装程序。您可以像使用 shell 脚本一样使用它(它是一个 shell 脚本),但会附加所有数据,然后脚本会加载并使用这些数据。您还可以将二进制文件直接嵌入到您的可执行文件中,然后将它们映射为可执行代码,然后执行它们。不确定你是否可以 exec
内存区域,否则你需要挂接到应用程序代码并执行一些巫毒魔法来初始化和加载所需的所有库(也许你可以使用 dyld.so那个)。
将实用程序的源代码合并到您的程序中,并自己调用它们的底层过程(这意味着您自己处理它们 main
所做的任何事情)。
就我个人而言,我会选择选项 2,如果必须的话,我会选择选项 4。
切记在任何这些情况下尊重所有软件许可。
我目前正在开发一个新项目,一个必须包含许多 Unix 实用程序(如 Busybox)的二进制文件。
例如,我希望能够像这样在我的工具箱中使用 netcat(具有静态依赖项):
./mytoolbox netcat
但是我不知道怎么执行。
此应用的哪种架构最好?
感谢您的帮助。
一种可能的方法是将符号链接指向您的可执行文件。因此,首先将 mytoolbox
executable file (in elf(5) format) and add symlinks (see ln(1), symlink(2), symlink(7), inode(7), credentials(7)...) like ln -s mytoolbox mytoolchain
. Then the file mytoolchain
is a symbolic link 构建为可执行文件 mytoolbox
.
然后,启动您的 main
函数:
int main(int argc, char**argv) {
if (!strcmp(argv[0], "mytoolbox"))
run_prog_my_toolbox(argc, argv);
else if (!strcmp(argv[0], "mytoolchain"))
run_prog_my_toolchain(argc, argv);
另一种可能性是使用 dlopen(3) and dlsym(3).
加载插件您的 mytoolbox
可执行文件可能有依赖项。参见 execve(2), ldd(1), readelf(1)
例如,查看 GNU bash, which behaves differently when started as bash
or as rbash
(it then becomes a restricted shell) 的源代码。
考虑使用 GNU guile, Lua, or or code generating libraries such as libgccjit.
这样的解释器注意 software licensing 问题。如果您重新分发可执行文件,LGPLv3 可能是相关的(对于 libc.so.6
)
有几种方法可以做到这一点:
要求系统中存在这些工具。从开发人员的角度来看,这是迄今为止最简单的选择,但也有一些缺点。它不太安全(你调用的是什么版本?)并且你需要处理命令版本之间的各种差异。
不要再认为您需要一个二进制文件。没有严肃的应用程序甚至会考虑这一点,因为一旦它达到任何合适的大小,link 时间就不值得了。只需将您想要的实用程序与您的应用程序一起发送并直接调用它们。
将应用程序嵌入到您的启动程序中 script/binary。将数据嵌入“脚本”的一个例子是 NVIDIA 驱动程序安装程序。您可以像使用 shell 脚本一样使用它(它是一个 shell 脚本),但会附加所有数据,然后脚本会加载并使用这些数据。您还可以将二进制文件直接嵌入到您的可执行文件中,然后将它们映射为可执行代码,然后执行它们。不确定你是否可以
exec
内存区域,否则你需要挂接到应用程序代码并执行一些巫毒魔法来初始化和加载所需的所有库(也许你可以使用 dyld.so那个)。将实用程序的源代码合并到您的程序中,并自己调用它们的底层过程(这意味着您自己处理它们
main
所做的任何事情)。
就我个人而言,我会选择选项 2,如果必须的话,我会选择选项 4。
切记在任何这些情况下尊重所有软件许可。