包含二进制可执行文件的 Bash 脚本
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18410785/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bash script containing binary executable
提问by Katarzyna Gola
Is it possible to write a bash script, which would contain a binary executable program inside?
是否可以编写一个 bash 脚本,其中包含一个二进制可执行程序?
I mean a script, which would contain a dump of an executable in a textual form, which will be dumped back to an executable by this script when it is executed?
我的意思是一个脚本,它包含一个文本形式的可执行文件的转储,当它被执行时,它将被这个脚本转储回一个可执行文件?
I would love to know a solution, which will work out of the box without a need of installing additional packages. Is it possible?
我很想知道一个解决方案,它可以开箱即用,无需安装额外的软件包。是否可以?
Thanks!
谢谢!
采纳答案by Zoltán Haindrich
i never done something like this before ;)
this will compile some c source, create a b.bash
script containing the binary (and the original script for simple development)
我以前从未做过这样的事情;) 这将编译一些 c 源代码,创建一个b.bash
包含二进制文件的脚本(以及用于简单开发的原始脚本)
(a.bash)
(惑)
#!/bin/bash
if [ "bash a.bash ;bash b.bash
" == "b.bash" ];then
tail -n +$[ `grep -n '^BINARY' #!/bin/bash
xxd -r >foo <<'EndHere'
0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............
0000010: 0200 3e00 0100 0000 e003 4000 0000 0000 ..>.......@.....
0000020: 4000 0000 0000 0000 000a 0000 0000 0000 @...............
0000030: 0000 0000 4000 3800 0800 4000 1e00 1b00 [email protected]...@.....
0000040: 0600 0000 0500 0000 4000 0000 0000 0000 ........@.......
0000050: 4000 4000 0000 0000 4000 4000 0000 0000 @.@.....@.@.....
...
0001960: 6400 5f65 6461 7461 006d 6169 6e00 5f69 d._edata.main._i
0001970: 6e69 7400 nit.
EndHere
chmod +x foo
./foo
|cut -d ':' -f 1` + 1 ] $ shar binaryfile > binaryfile.shar
| base64 -d > a2.out
chmod +x a2.out
./a2.out
echo $?
exit
fi
cat "#!/bin/bash
lineCount=$(wc -l "" | cut -f 1 -d ' ') # just get the line count
((lineCount+=2)) # because we are going to append a line
head -n 1 "" > "" # this is done to ensure that shebang is preserved
echo "trap 'tail -n +$lineCount $0 > binary; chmod +x binary; ./binary' EXIT" >> ""
tail -n +2 "" >> ""
cat "" >> ""
exit 0
" > b.bash
echo "BINARY" >> b.bash
cat > a.c << EOF
int main(){
return 12;
}
EOF
gcc a.c
base64 a.out >> b.bash
invoke with (a.bash generates b.bash):
调用(a.bash 生成 b.bash):
./binarymaker myscript mybinary resultscript
i don't know how to evade writing out the binary into a temporary file before execution...
我不知道如何避免在执行前将二进制文件写入临时文件...
回答by stark
I tried this out and it works. Hex was generated with xxd.
我试过了,它有效。十六进制是用 xxd 生成的。
tail -n +$lineCount $0 | source /dev/stdin
回答by jlliagre
Don't reinvent the wheel like several other answers are suggesting, just use the venerable sharcommand which is precisely doing this by design.
不要像其他几个答案所建议的那样重新发明轮子,只需使用古老的shar命令,它正是通过设计来做到这一点的。
Assuming the file you want to embed in your script is binaryfile
, simply run
假设您要嵌入脚本的文件是binaryfile
,只需运行
#!/usr/bin/env bash
get_length()
{
ls -l "" | cut -f5 -d' '
}
# First parameter is the number of semicolons to add to second parameter
# NOTE: we do not use an "add_blanks" function directly because it seems bash
# removes duplicated blanks. The workaround is adding other character and
# replacing later using e.g. sed.
add_semicolons()
{
scratch=""
for n in $(seq 1 )
do
scratch+=";"
done
echo $scratch
}
# Default values
output="installer"
input="deployable.tar.gz"
shell="busybox"
shell_len=$(get_length "$shell")
payload_len=$(get_length "$input")
# START OF INSTALLATION SCRIPT GENERATION.
#
# Note: generated scripts reserves 9 digits for the skip (ibs) offsets.
# When the script is first written, these digits are written as semicolons.
# Later when the lengths are computed, these semicolons are replaced by the
# correct numbers, but the 9-digit length must be preserved by adding blanks
# until 9 digits are filled. Failure to do this will cause the script length
# to vary and offsets would need to be iteratively computed.
# Add shebang
echo "#!/usr/bin/env ash" > "$output"
echo "echo Extracting installer..." >> "$output"
# Add lines to extract binary data and extract payload
echo "mkdir -p /tmp/installer" >> "$output"
echo "dd if=\"$(basename $output)\" ibs=;;;;;;;;; skip=1 | dd ibs=$shell_len count=1 of=/tmp/installer/shell 2>/dev/null" >> "$output"
echo "chmod +x /tmp/installer/shell" >> "$output";
echo "dd if=\"$(basename $output)\" ibs=;;;;;;;;; skip=1 2>/dev/null of=/tmp/installer/payload.tar.gz 2>/dev/null" >> "$output"
# From here on, the binary extraction is completed, do something with extracted files...
# [...]
# Use exit command to avoid the shell script parsing to reach the binary part
echo "echo Done!" >> "$output"
echo "exit 0" >> "$output"
# We reserved 9 blanks for the ibs offsets. Thus fill offsets with blanks up to 9 chars total
script_len=$(get_length "$output")
skip_len=$((script_len + shell_len))
to_add=$((9 - ${#script_len}))
script_len_str=$(add_semicolons $to_add $script_len)
to_add=$((9 - ${#skip_len}))
skip_len_str=$(add_semicolons $to_add $skip_len)
# Add skip values
sed -i "4s/ibs=;;;;;;;;;/ibs=$script_len_str/" "$output"
sed -i "4s/;/ /g" "$output"
sed -i "6s/ibs=;;;;;;;;;/ibs=$skip_len_str/" "$output"
sed -i "6s/;/ /g" "$output"
cat "$shell" >> "$output"
cat "$input" >> "$output"
chmod +x "$output"
and you are set. You have a shell script named binaryfile.shar
which when executed will extract binaryfile
.
你已经准备好了。您有一个名为的 shell 脚本binaryfile.shar
,执行时将提取binaryfile
.
回答by dcaswell
You can convert your binary to text, and then back to binary using uuencode/uudecode.
您可以将二进制文件转换为文本,然后使用 uuencode/uudecode 将其转换回二进制文件。
http://linux.die.net/man/1/uuencode
http://linux.die.net/man/1/uuencode
So you can store your binary data as text in your script and output it to a binary file.
因此,您可以将二进制数据作为文本存储在脚本中并将其输出到二进制文件中。
uuencode binaryFile > output.txt
uuencode binaryFile > output.txt
And then put that data into your script and when creating the binary file use uudecode.
然后将该数据放入您的脚本中,并在创建二进制文件时使用 uudecode。
回答by Aleks-Daniel Jakimenko-A.
So, if I got it right you want to include a binary in your script and execute it on script exit?
那么,如果我猜对了,您想在脚本中包含一个二进制文件并在脚本退出时执行它吗?
Here is a binarymaker
script(This does not only create a script that extracts a binary, but merges any your script with any binary):
这是一个binarymaker
脚本(这不仅会创建一个提取二进制文件的脚本,还会将您的任何脚本与任何二进制文件合并):
echo $binary > file
You should run it like this
你应该像这样运行它
##代码##If you run resultscript
then both myscript
and mybinary
are going to be executed. You can optionally add a command to rm
the binary afterwards.
如果你运行resultscript
那么这两个myscript
和mybinary
将要执行。之后您可以选择向rm
二进制文件添加命令。
Also, do not forget to exitat the end of your script because otherwise it will continue and try to parse binary data.
另外,不要忘记在脚本结束时退出,否则它将继续并尝试解析二进制数据。
If you're working with another script and not a binary, then it can be executed from pipe like this:
如果您正在使用另一个脚本而不是二进制文件,则可以像这样从管道中执行它:
##代码##But it is not going to work on real binaries. Also, it doesn't work if your bash version is under 4
但它不适用于真正的二进制文件。此外,如果您的 bash 版本低于 4,则它不起作用
回答by Jesús Alonso
I had to make a installer script to deploy it on a machine that did not even have tar, and I ended embedding busybox (for tar and gunzip) and the tarball to deploy on a shell script. I did it the dd way:
我必须制作一个安装程序脚本才能将它部署在一台甚至没有 tar 的机器上,并且我结束了嵌入 busybox(用于 tar 和 gunzip)和要部署在 shell 脚本上的 tarball。我是按照 dd 的方式做的:
##代码##回答by Stefan
Sure it is!
就是这样!
You can for example dump any binary into a file with:
例如,您可以使用以下命令将任何二进制文件转储到文件中:
##代码##There are many installation scripts which do things like that.
有许多安装脚本可以做这样的事情。