向 Shell 脚本添加二进制有效负载
通常当我们想到 shell 脚本时,我们想到的是可编辑的文本,但是也可以向您的 shell 脚本添加二进制数据。 在这种情况下,我们将讨论将二进制有效负载添加到 shell 脚本的末尾。
例如,将二进制有效负载添加到 shell 脚本可以用于创建一个单一文件的 shell 脚本,该脚本可以安装您的整个软件包,而该软件包可能由数百个文件组成。 您只需将软件包的 tar 或 gzip 文件作为二进制有效负载附加到脚本文件,当脚本运行时,它会提取有效负载并使用提取的文件执行其任务。
对于此示例,我假设附加的文件是一个tar.gz文件。 有效负载附加到安装脚本的末尾,前面是一个标记行 (PAYLOAD:)。 附加的数据是 uuencoded 或只是二进制数据。 以下脚本采用一个参数,该参数应为tar.gz附加到安装脚本的参数。 该安装脚本模板install.sh.in被复制到install.sh并附加了有效负载。 该脚本命名为addpayload.sh如下
#!/bin/bash
# Check for payload format option (default is uuencode).
uuencode=1
if [[ "$1" == '--binary' ]]; then
binary=1
uuencode=0
shift
fi
if [[ "$1" == '--uuencode' ]]; then
binary=0
uuencode=1
shift
fi
if [[ ! "$1" ]]; then
echo "Usage: $0 [--binary | --uuencode] PAYLOAD_FILE"
exit 1
fi
if [[ $binary -ne 0 ]]; then
# Append binary data.
sed \
-e 's/uuencode=./uuencode=0/' \
-e 's/binary=./binary=1/' \
install.sh.in >install.sh
echo "PAYLOAD:" >> install.sh
cat $1 >>install.sh
fi
if [[ $uuencode -ne 0 ]]; then
# Append uuencoded data.
sed \
-e 's/uuencode=./uuencode=1/' \
-e 's/binary=./binary=0/' \
install.sh.in >install.sh
echo "PAYLOAD:" >> install.sh
cat $1 | uuencode - >>install.sh
fi
除了附加有效负载之外,它还会修改安装程序脚本,以告诉它有效负载是二进制的还是 uuencoded 的。
模板脚本install.sh.in是我们的安装脚本,此时它只是解压有效负载,没有其他操作。 实际上,它甚至没有解压有效负载,而只是使用tar的-t选项进行测试。
#!/bin/bash
uuencode=1
binary=0
function untar_payload()
{
match=$(grep --text --line-number '^PAYLOAD:$' $0 | cut -d ':' -f 1)
payload_start=$((match + 1))
if [[ $binary -ne 0 ]]; then
tail -n +$payload_start $0 | tar -tzvf -
fi
if [[ $uuencode -ne 0 ]]; then
tail -n +$payload_start $0 | uudecode | tar -tzvf -
fi
}
read -p "Install files? " ans
if [[ "${ans:0:1}" || "${ans:0:1}" ]]; then
untar_payload
# Do remainder of install steps.
fi
exit 0
在函数untar_payload中,脚本使用grep搜索自身 ($0) 以查找标记,然后从grep输出中提取行号并将其加一。 然后,此行号传递给tail,前面带有一个加号,这会导致tail输出从该行号开始的所有内容。 如果有效负载是二进制的,则数据会直接输入到tar以进行提取。 如果是 uuencoded 的,则它首先被馈送到uudecode,然后才被馈送到tar.
要创建我们的安装程序,让我们使用一个简单的有效负载文件,其中包含三个文件,名称分别为 a、b 和 c。 我们将有效负载添加为 uuencoded 块
$ sh addpayload.sh --uuencode abc.tar.gz $ cat install.sh #!/bin/bash ... # Installer script lines (see above) read -p "Install files? " ans ... # More installer script lines (see above) exit 0 PAYLOAD: begin 644 - M'XL(`))%G$D``^W12PJ$0`Q%T2REEI!HK%J/BM`]Z(F?_?O#J8+0&=TS"8'` M"[Q6_D\WV7V?5AH]=COWBYB9%_4J:Q$UK6J7I`&_R3+-[9B2_+YS_[F]&\8I JXJ%874#&J_X;^H_0!V2\ZC_3/P```````````````/!D!0OB?_,`*``` ` end
在文件末尾,您会看到PAYLOAD标记和 uuencoded 块。 如果我们现在运行该脚本,我们将得到
$ sh install.sh Install files? y -rw-r--r-- mitch/users 0 2009-02-18 11:29 a -rw-r--r-- mitch/users 0 2009-02-18 11:29 b -rw-r--r-- mitch/users 0 2009-02-18 11:29 c
我不会向您展示--binary用法,但它会产生相同的结果,尽管占用空间略小,因为有效负载不必是 uuencoded 的。