Shell 自解压安装脚步
来源:互联网 发布:随机抽取名字软件 编辑:程序博客网 时间:2024/05/29 10:41
经常在安装程序的时候直接通过一个 shell 脚步就完成了,个人觉得这种方式也是挺方便的。于是就研究了一下,发现其实实现起来也并不复杂,本文主要记录一下整个制作过程。
我目前了解到的 shell 自解压的安装脚步制作方式分为两种:
- sharutils - 利用 sharutils 工具对多个文件进行归档,同时生成一个 shell 脚步用于取出这些文件。该脚步中包含编码后的二进制或压缩包等文件的信息以及解码操作。这种方式需要依赖于 sharutils 工具,不够灵活。
- 自己通过 shell 命名实现 - 这种方式几乎能在所有的 Linux 平台运行,不依赖于特定工具。
为了简化操作,我采用了一个简单的 helloworld 工程目录,然后利用脚步对其进行解压并对该工程进行编译来模拟安装。
$ tree helloworldhelloworld/ main.c Makefile$ cat helloworld/main.c#include <stdio.h>int main(){ printf("Hello world!\n"); return 0;}$ cat helloworld/Makefile.PHONY: allall: helloworldhelloworld: main.o gcc -o $@ $^%.o: %.c gcc -o $@ -c $<.PHONY: cleanclean: rm -rf *.o helloworld
通过修改编译过程为安装过程即可实现脚步自动话安装。这里就只提供思路,不具体给出安装的示例了,希望大家可以举一反三。
Sharutils
Sharutils 是从许多文件中制作所谓的 shell 档案,准备通过电子邮件服务传输的工具。本文主要使用 shar 命令对多个文件进行归档,并调用其中的 shell 脚步执行基本的操作。在这之前需要首先安装 sharutils 工具集,在 Ubuntu 下使用如下命令:
$ sudo apt-get install -y sharutils
首先,我们对 helloworld 进行压缩
$ tar -czvf helloworld.tgz helloworldhelloworld/helloworld/main.chelloworld/Makefile
接着我们使用 shar 对压缩包进行编码并重定向到 compile.sh 脚步中
$ shar helloworld.tgz > compile.shshar: Saving helloworld.tgz (text)$ cat compile.sh#!/bin/sh# This is a shell archive (produced by GNU sharutils 4.15.2).# To extract the files from this archive, save it to some FILE, remove# everything before the '#!/bin/sh' line above, then type 'sh FILE'.#lock_dir=_sh11831# Made on 2017-10-13 10:25 CST by <japin@ww-it>.# Source directory was '/home/japin/WwIT/Codes/self-extract'.## Existing files will *not* be overwritten, unless '-c' is specified.## This shar contains:# length mode name# ------ ---------- ------------------------------------------# 344 -rw-rw-r-- helloworld.tgz#MD5SUM=${MD5SUM-md5sum}f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`test -n "${f}" && md5check=true || md5check=false${md5check} || \ echo 'Note: not verifying md5sums. Consider installing GNU coreutils.'if test "X$1" = "X-c"then keep_file=''else keep_file=truefiecho=echosave_IFS="${IFS}"IFS="${IFS}:"gettext_dir=locale_dir=set_echo=falsefor dir in $PATHdo if test -f $dir/gettext \ && ($dir/gettext --version >/dev/null 2>&1) then case `$dir/gettext --version 2>&1 | sed 1q` in *GNU*) gettext_dir=$dir set_echo=true break ;; esac fidoneif ${set_echo}then set_echo=false for dir in $PATH do if test -f $dir/shar \ && ($dir/shar --print-text-domain-dir >/dev/null 2>&1) then locale_dir=`$dir/shar --print-text-domain-dir` set_echo=true break fi done if ${set_echo} then TEXTDOMAINDIR=$locale_dir export TEXTDOMAINDIR TEXTDOMAIN=sharutils export TEXTDOMAIN echo="$gettext_dir/gettext -s" fifiIFS="$save_IFS"if (echo "testing\c"; echo 1,2,3) | grep c >/dev/nullthen if (echo -n test; echo 1,2,3) | grep n >/dev/null then shar_n= shar_c='' else shar_n=-n shar_c= ; fielse shar_n= shar_c='\c' ; fif=shar-touch.$$st1=200112312359.59st2=123123592001.59st2tr=123123592001.5 # old SysV 14-char limitst3=1231235901if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \ test ! -f ${st1} && test -f ${f}; then shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'elif touch -am ${st2} ${f} >/dev/null 2>&1 && \ test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'elif touch -am ${st3} ${f} >/dev/null 2>&1 && \ test ! -f ${st3} && test -f ${f}; then shar_touch='touch -am $3$4$5$6$2 "$8"'else shar_touch=: echo ${echo} 'WARNING: not restoring timestamps. Consider getting andinstalling GNU '\''touch'\'', distributed in GNU coreutils...' echofirm -f ${st1} ${st2} ${st2tr} ${st3} ${f}#if test ! -d ${lock_dir} ; then :else ${echo} "lock directory ${lock_dir} exists" exit 1fiif mkdir ${lock_dir}then ${echo} "x - created lock directory ${lock_dir}."else ${echo} "x - failed to create lock directory ${lock_dir}." exit 1fi# ============= helloworld.tgz ==============if test -n "${keep_file}" && test -f 'helloworld.tgz'then${echo} "x - SKIPPING helloworld.tgz (file already exists)"else${echo} "x - extracting helloworld.tgz (text)" sed 's/^X//' << 'SHAR_EOF' | uudecode &&begin 600 helloworld.tgzM'XL(`+4CX%D``^W4STO#,!0'\%[W_HKGW&`35I-V:Z`;XG$7?UP%$4K6N6K6MCJS#@_B_VQ9&"Z)#L,KP^SDT)0E)VO=>5K$QV4MFS>+<:8LH*#4I6ZDFHMGNM.=*72@A/"K^8)SU/*(<GK9VH8;?-(\OL/$6;)/UBWJ'Q([6JX[^.DM35+>Q1M!C@(QI_&7TJUC[]0OBKB[_LB<%BT<)8/_GG\3Y-4F]TBYMDV7R29N[H@2M*<MRV08#.F5N+"Q1==RT)V7R<)5MIS<I]WAM!JU<;ZS*8LIO=%??PY\4Z/^KZ+GM>)F8^,?W.%3_Q:U?U[\GROH/Q@+U_QO<V_G-]5W(D3%$Q2/D.B.(ZO>PNA'<MC#J/6O,HX]XE]QZ(^FX6<M_5S?Z1YMZ,:+^T-G&4$E5-2!V[YI%=\IF;-;?Z=Z_\```````````````````!PS-X!M-<!Y0`H``"4`endSHAR_EOF (set 20 17 10 13 10 23 22 'helloworld.tgz' eval "${shar_touch}") && \ chmod 0664 'helloworld.tgz'if test $? -ne 0then ${echo} "restore of helloworld.tgz failed"fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'helloworld.tgz': 'MD5 check failed' ) << \SHAR_EOF78be4fbc5349d5028fb6cac108fa39d5 helloworld.tgzSHAR_EOFelsetest `LC_ALL=C wc -c < 'helloworld.tgz'` -ne 344 && \ ${echo} "restoration warning: size of 'helloworld.tgz' is not 344" fifiif rm -fr ${lock_dir}then ${echo} "x - removed lock directory ${lock_dir}."else ${echo} "x - failed to remove lock directory ${lock_dir}." exit 1fiexit 0
从上面的 compile.sh 脚步中可以看到 shar 编码的文件信息。如果运行上面的 compile.sh 脚步,他只会将 helloworld.tgz 压缩包还原出来,若想要它自动编译,我们还需要在该脚步返回前添加必要的操作。
在上述 compile.sh 脚步最后的 exit 0
前加入下面的内容:
echo "x - decompressing helloworld.tgz."tar -xf helloworld.tgzif test $? -ne 0then echo "decompress helloworld.tgz failed" exit 1fi # Remove helloworld.tgz and auto-compile helloworldecho "x - compiling helloworld"rm helloworld.tgz && cd helloworld && makeif test $? -ne 0then echo "compile helloworld failed" exit 1fi
此时,运行 compile.sh 脚步即可将该脚步中的 helloworld.tgz 还原并解压为 helloworld 目录,同时将中间文件 helloworld.tgz 删除,随后对 helloworld 进行编译。
Shell 实现
该方式思想与 sharutils 相同,唯一不同的是 sharutils 对压缩包、二进制文件等可以采用不同的编码方式,而采用 shell 的实现则是直接将压缩包或二进制文件等写入到脚步中。这里我们同样采用 helloworld 来给出 shell 的实现方式。
首先,我们创建一个脚步用于解压 helloworld.tgz 文件:
$ cat shell-compile.sh#!/bin/bashmain(){ ARCHIVE=$(awk '/^__ARCHIVE_BELOW__/ {print NR + 1; exit 0;}' $0) tail -n+$ARCHIVE $0 | tar xz >/dev/null 2>&1 cd helloworld && make exit 0}main# This line must be the last line of the file__ARCHIVE_BELOW__
该文件中需要注意几点:
- __ARCHIVE_BELOW__ - 用于标识该文件中的压缩文件数据,即 helloworld.tgz 的数据,并且该行只能在文件的末尾。
- awk - 用于查找 helloworld.tgz 数据的开始行。
- tail - 用于解析 helloworld.tgz 的数据并利用管道传递给 tar 进行解压。
- exit - mian() 函数中的 exit 命令是不可少的。如果没有该命令,shell 脚步会继续执行后面的内容导致出错。
接着,我们就将 helloworld.tgz 的数据放置在该文件之后,这样就可以实现脚步自解压编译了
$ cat helloworld.tgz >> shell-compile.sh
完成上述步骤之后,我们就可以通过 shell-compile.sh 获取到 helloworld 目录,并对 helloworld 进行编译。
参考
[1] 在shell中嵌入二进制文件
[2] Bash Self-Extracting Script
- Shell 自解压安装脚步
- shell下制作自解压安装包
- shell下制作自解压安装包
- shell 脚步
- shell+tar 自解压脚本
- linux自解压安装脚本
- 制作自解压安装文件
- [linux]shell脚步记录
- 一些常用shell脚步
- CMake调用shell脚步
- shell 脚步分析数据
- 发掘WinRAR的“自解压安装”功能
- Winrar制作自解压安装程序
- 自解压安装包制作软件
- 制作企业版中的自解压安装包?
- mysql5.7自解压的正确安装
- 7z制作自解压安装包
- 清理缓存的shell脚步
- 87、使用TensorBoard进行可视化学习
- UnsatisfiedLinkError:libwebviewchromium.so is 32-bit instead of 64-bit
- C++ limits头文件的用法(numeric_limits)
- 88、展示Tensorflow计算图上每个节点的基本信息以及运行时消耗的时间和空间
- 572. Subtree of Another Tree (另一个树的子树)
- Shell 自解压安装脚步
- 《Spring 5 官方文档》16.ORM和数据访问
- POJ
- 88、使用tensorboard进行可视化学习,查看具体使用时间,训练轮数,使用内存大小
- 正则表达式常用字符查阅表
- node-sass安装失败问题
- 李飞飞:从清洁工到斯坦福教授,我是如何成功逆袭的?
- poj2457 Part Acquisition
- 89、tensorflow使用GPU并行计算