linux版的jdk安装包是一个.bin后缀文件,下载后给执行权限就能解压安装,即简单又方便,Nvidia的闭源驱动(.run)也是一样。一直以为这两个安装包是编译好的二进制文件,可安装过程怎么看都像shell脚本,用sh -x 看了下执行过程,果然就是一个shell脚本,只不过脚本最后嵌入了二进制文件。
JDK安装的大致流程:检查磁盘空间 --> 提取包含的二进制文件(UnZipSFX自解压文件)--> 检查checksum --> 解压 -->结束
Nvidia的脚本稍复杂一点,但大致流程也是一样的,照着写了一个例子,可以用来制作包含二进制文件的shell安装包:

#!/bin/sh
PATH=/usr/bin:/bin
umask 022
md5=0ee8c59a12d99fdfd1e95bfda6938e86
pre_install()
{
echo "准备安装环境(略)..."
mkdir ./install.tmp.$$
}
check_sum()
{
if [ -x /usr/bin/md5sum ]&&[ -f "install.tmp.$$/extract.$$" ]; then
echo "正在检查md5......"
sum_tmp=($(/usr/bin/md5sum install.tmp.$$/extract.$$))
if [ $sum_tmp != $md5 ]; then
    echo "文件md5不一致,请检查文件完整性,退出!"
    exit 1
fi
else
        echo "找不到md5sum命令或文件未提取,退出"
    exit 1
fi
}
extract()
{
echo "从脚本中提取文件"
line_number=`awk '/^__BIN_FILE_BEGIN__/ {print NR + 1; exit 0; }' "$0"`    
tail -n +$line_number "$0" >./install.tmp.$$/extract.$$
#tail -n +$line_number "$0" >./install.tmp.$$/extract_tmp.$$
#base64 -d ./install.tmp.$$/extract_tmp.$$ >./install.tmp.$$/extract.$$
}
install()
{
    echo "安装中(略)..."
}
post_install()
{
    echo "配置中(略)..." 
    echo "清理临时文件"
    rm -rf install.tmp.$$
}

main()
{
    pre_install
    extract
    check_sum
    install
    post_install
    exit 0
}

main
#这行下面接二进制文件
__BIN_FILE_BEGIN__

二进制文件可以是zip/tar/可执行文件等等,将文件追加到脚本里,例如追加zip文件到脚本里:

cat binary.zip >>shell.sh

这种方法提取后会改变binary.zip的md5值,校检的时候要用提取后文件的md5(./install.tmp.$$/extract.$$)
还有一种方法可以不改变binary.zip的md5,就是使用base64将文件加密成文本:

base64 binary.zip >>shell.sh

在脚本extract()中,使用注释里的命令,网上有很多教程是用uuencode加密的,这个也行,不过很多系统默认是没有安装uuencode,通用性会下降,还是用base64好