向 Shell 脚本添加二进制有效负载

作者:Mitch Frazier

通常当我们想到 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 的。

Mitch Frazier 是 Emerson Electric Co. 的嵌入式系统程序员。 自 2000 年代初以来,Mitch 一直是 Linux Journal 的撰稿人和朋友。

加载 Disqus 评论