绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
如何用 Bash 创建一个二进制发布包
2017-06-29 15:06:15

点击上方蓝字 与 “CU技术社区” 一起玩耍哦~

作者:kinkuo

原文链接:http://www.jianshu.com/p/0cc02fa6eb87


Linux 下安装 JDK 的时候,Sun 公司为 JDK6 的 linux 版本提供了一个 shell 的安装包,用起来特别的好用,基本上和在 Windows 下安装软件没什么两样,shell 文件执行之后,几乎一切都系都设置好了,不用我们自己再动手设置 PATH 和 JAVA_HOME,可是一个 shell 文件中是如何把二进制代码包含进来的呢?


再例如淘宝为 linux 开发的淘宝插件,其实也是一个 shell 文件,但是执行这个 shell 文件之后,会安装很多二进制的东西,同样的问题,Shell 只是文本文件,其中的二进制是怎么来包含进来的呢?


从文本文件转换出可执行文件,通过编译器把源程序编程成可执行程序当然是可以的,但是前面提到的哪两种情况都不是这样做的。原因有两个,对于大的项目来说,编译需要的时间比较长,环境比较复杂; 第二,更加重要的是,这样做其实和从源代码编译程序没什么两样,对于不想让用户看到自己的源码的商业软件来说,这显然是不可取的。




我们看看一般的程序是如何发布二进制包的。


一般的程序,无非是把二进制和必要的文档压缩到一个压缩文件中,然后通过 README 文档的解释程序的运行依赖什么样的假设,然后,你就可以把程序自行的移动到你想移动的地方去了。


很多时候,我们把程序放到任何地方都是可以运行的,但是程序可以运行,并不是说我们已经完成了程序的安装,举个例子来说,如果我们解压 JDK 的二进制包之后,直接把程序移动到一个地方,然后把对应的 bin 目录添加到 PATH 中就可以执行 JDK 提供的一系列工具了。


但是如果我们安装其他的依赖与 JDK 的程序的时候,比如 TOMCAT,那么就会有问题。因为我们只是在 PATH 中加入了 JDK 的 bin 目录而没有制定 JAVA_HOME 这个环境变量,所以 TOMCAT 很可能会不能运行。


再比如我们使用 man 命令来查看一个程序的手册,一般情况下二进制包中也会包含 man 文档的,但是如果我们只是把解压的二进制包的路径添加到了 PATH 中,还不能在 man 中找到对应的文档。


也正是因为这样的原因吧,所以很多的二进制包的发布是使用 deb 或者 rpm 包来发布。安装的时候少了很多的烦恼。要制做 deb 或者 rpm 包当然是需要学习成本的,而且 deb 和 rpm 也只能在对应的 linux 发行版中使用,如果想要为所有的 Linux 发行版都提供一个安装文件,那么使用 shell 文件来做无疑是好的办法。



Shell 的学习成本低,而且对 linux 平台来说有通用,那么是如何做到的呢?



想想我们在手动安装的情形,无非是把压缩的二进制包解压,移动到特定的目录下,在 PATH 变量中添加二进制包的可执行文件的路径等等工作。首先我们把二进制包压缩文件和 shell 文件分开。这样一来,shell 中只要完成解压,然后把解压后的目录移动到指定的目录中去,设置各种各样的环境变量然后就完成了工作了。



但是我们在如何把压缩文件和这个 shell 解压之后要执行的命令的 shell 文件一起放到一个 shell 文件中呢?



要做到这一点,首先这个 shell 文件中,要有可以解压的二进制内容,其次,这个 shell 要做的工作就是,把二进制内容,解压,然后把原来手动做的工作在这个 shell 中用命令完成。再用 shell 写个脚本完成一些手动完成的工作,这个任务比较容易,所以制作 shell 安装包的难点就是如何在其中包含二进制内容了。



如何在一个文本文件中记录二进制的内容呢?


这个问题早就被解决了。答案就是使用 Base64 编码。在 linux 下就有 base64 这个命令程序就是来做这个工作的。base64 可以把文件进行 base64 的编码,输出的标准输出中去或者把文件中的 Base64 编码的内容解码。命令 base64 除了可以对文件的内容做 Base64 的编解码外,也可以对标准输入中的数据进行 Base64 编辑码。


有了这些预备的知识,那么我们就可以看看具体的如何来做 shell 的二进制发布包了。


首先假设我们要发布的文件都放在名为 test 的当前文档中。


1. 把要发布的文件打包


  1. base64 ./test.tar > test_base64.txt



2. 对打好的二进制包做 Base64 编码



  1. base64 ./test.tar > test_base64.txt




3准备安装文件的 shell 文件



  1. test_base64="";#test_base64中的所有内容

  2. echo $test_base64|base64 -d >test.tar

  3. tar zxf test.tar

  4. rm test.tar

  5. # 其他的安装代码


写到这里,我们已经把道理将明白了。


但是可不可以写一个 shell 程序,专门来生成这样的发布包软件呢?


当然可以。


下面是我写的这个打包程序的源代码。



4 下面是我写的这个打包程序的源代码



  1. function mkpackage(){

  2.    target_dir=$1

  3.    felow_install_shell_command_file=$2

  4.    echo "tar -zcf ._test_dir.tar.gz $target_dir"

  5.    tar -zcf ._test_dir.tar.gz $target_dir

  6.    base64 ._test_dir.tar.gz >._base64

  7.    rm ._test_dir.tar.gz

  8.    printf "test_base64=\"">install.sh

  9.    while IFS='' read -r line || [[ -n "$line" ]]; do

  10.    printf "$line\\" >>install.sh

  11.    printf "n" >>install.sh

  12.    done <./._base64

  13.    rm ._base64

  14.    echo "\"" >>install.sh

  15.    echo 'printf $test_base64|base64 -d >._temp.tar.gz;'>>install.sh

  16.    echo 'tar zxf ._temp.tar.gz' >> install.sh

  17.    echo 'rm ._temp.tar.gz' >>install.sh

  18.    if [[ -e $fellow_install_shell_command_file ]]; then

  19.        cat $fellow_install_shell_command_file >>install.sh

  20.    fi

  21.    chmod +x install.sh

  22. }

  23. function usage(){

  24.   echo "usage:"

  25.   echo "    $1 test_dir [the_command.sh]"

  26. }

  27. if [[ $# != 0 ]]

  28. then

  29.    mkpackage $1 $2

  30. else

  31.   usage $0

  32. fi



这个程序接受两个输入参数,个表示要打的程序包目录,第二个是解压后,安装动作的 shell 脚本文件。后这个程序生成一个名为 install.sh 的文件。执行 install.sh 之后,会首先得到加压的程序包内容,然后执行第二个参数指定的 shell 脚本的内容。这样我们就做了用 Shell 发布二进制文件的一个打包程序。当然了,在后发布之前,还需要把这个 shell 压缩一下。以便消除因为 Base64 编码而带来的文件长度的变大的影响。






分享好友

分享这个小栈给你的朋友们,一起进步吧。

专业的官方救援小分队
创建时间:2019-11-07 09:33:49
我是一个官方吐槽小栈我们是技术栈的搬砖IT民工。 我知道你们在使用小栈的过程中会遇到很多问题: 迭代功能太鸡肋? 界面太low? 编辑器难用到爆? ··· 需求尽管提,槽点尽管说,技术救援小分队在线为您灭火,致力于提供专业的解答,提供迅疾的反馈。 悄悄的说,毛线不懂的运营喵、产品狗他们不在,我们一起吐槽!
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

栈主、嘉宾

查看更多
  • 山中老狐狸
    栈主
  • 栈栈
    嘉宾
  • gaokeke123
    嘉宾
  • Ys
    嘉宾

小栈成员

查看更多
  • gyu
  • aabbcc1832611
  • 飘絮絮絮丶
  • h313895741
戳我,来吐槽~