在shell脚本中嵌入可执行二进制文件

首先,我已经使用Google搜索,但只找到了将压缩文件(例如.tar.gz )嵌入到shell脚本中的示例。

基本上如果我有一个打印字符串的C程序( hello.c ),请说Hello World!

我编译它以获得可执行的二进制文件

 gcc hello.c -o hello 

现在我有一个shell脚本testEmbed.sh

我要问的是,是否可以在shell脚本中嵌入二进制文件( hello ),以便在运行时

 ./testEmbed.sh 

它执行二进制文件来打印Hello World!

澄清 :一种方法是将可执行文件压缩到一个存档中,然后在脚本运行时将其解压缩。 我要问的是,如果没有它可以运行程序。

到目前为止,我正在尝试这种方法。 但它对我不起作用。 我猜作者正在另一个架构上使用其他一些发行版。 所以,基本上这对我不起作用。 :P

另外,如果C程序的工作流程与Java jar不同,我也想知道!

是的,这可以做到。 它实际上与你的链接文章在概念上非常相似。 诀窍是使用uuencode将二进制文件编码为文本格式,然后将其添加到脚本的末尾。

然后编写脚本,使其在自身上运行uudecode以创建二进制文件,更改权限然后执行它。

uuencodeuudecode最初是为了将二进制内容转移到互联网的前身而创建的,互联网没有很好地处理二进制信息。 转换为文本意味着它也可以作为shell脚本发布。 如果由于某种原因,当您尝试运行uuencode ,您的发行版会抱怨,这可能意味着您必须安装它。 例如,在Debian Squeeze上:

 sudo aptitude install sharutils 

将为您获取相关的可执行文件。 这是我经历的过程。 首先创建并编译您的C程序hello.c

 pax> cat hello.c #include  int main (void) { printf ("Hello\n"); return 0; } pax> gcc -o hello hello.c 

然后创建一个shell脚本testEmbed.sh ,它将解码自己:

 pax> cat testEmbed.sh #!/bin/bash rm -f hello uudecode $0 ./hello rm -f hello exit 

第一个rm语句演示了hello可执行文件是由这个脚本重新创建的,而不是在编译中徘徊。 由于您还需要文件中的有效负载,因此将编码的可执行文件附加到其末尾:

 pax> uuencode hello hello >>testEmbed.sh 

然后,当您执行脚本testEmbed.sh ,它会提取可执行文件并运行它。

这个工作的原因是因为uudecode在其输入( beginend )中查找某些标记行,这些标记行由uuencode放置,因此它只尝试解码编码的程序,而不是整个脚本:

 pax> cat testEmbed.sh #!/bin/bash rm -f hello uudecode $0 ./hello rm -f hello exit begin 755 hello M?T5,1@$!`0````````````(``P`!````$(,$"#0```#`!@```````#0`(``' M`"@`'@`;``8````T````-(`$"#2`!`C@````X`````4````$`````P```!0! : : : M:&%N9&QE`%]?1%1/4E]%3D1?7P!?7VQI8F-?8W-U7VEN:70`7U]B 

您还应该担心其他一些问题,例如您的程序可能需要目标系统上不存在的共享库,但上述过程基本上就是您所需要的。


JAR文件的过程非常相似,只是您运行它的方式不同。 它仍然是单个文件,但您需要替换该行:

 ./hello 

能够运行JAR文件的东西,例如:

 java -jar hello.jar 

我认为makeself就是你所描述的。

执行此操作的可移植方法是使用printf命令和八进制转义:

 printf '\001\002\003' 

打印字节1,2和3.由于您可能不想手动编写所有内容, od -b命令可用于生成文件的八进制转储,然后您可以使用sed脚本来删除离开垃圾并将右侧反斜杠放在适当的位置。