Shell 自解压安装脚步
2017-10-13 11:14
176 查看
经常在安装程序的时候直接通过一个 shell 脚步就完成了,个人觉得这种方式也是挺方便的。于是就研究了一下,发现其实实现起来也并不复杂,本文主要记录一下整个制作过程。
我目前了解到的 shell 自解压的安装脚步制作方式分为两种:
sharutils - 利用 sharutils 工具对多个文件进行归档,同时生成一个 shell 脚步用于取出这些文件。该脚步中包含编码后的二进制或压缩包等文件的信息以及解码操作。这种方式需要依赖于 sharutils 工具,不够灵活。
自己通过 shell 命名实现 - 这种方式几乎能在所有的 Linux 平台运行,不依赖于特定工具。
为了简化操作,我采用了一个简单的 helloworld 工程目录,然后利用脚步对其进行解压并对该工程进行编译来模拟安装。
通过修改编译过程为安装过程即可实现脚步自动话安装。这里就只提供思路,不具体给出安装的示例了,希望大家可以举一反三。
首先,我们对 helloworld 进行压缩
接着我们使用 shar 对压缩包进行编码并重定向到 compile.sh 脚步中
从上面的 compile.sh 脚步中可以看到 shar 编码的文件信息。如果运行上面的 compile.sh 脚步,他只会将 helloworld.tgz 压缩包还原出来,若想要它自动编译,我们还需要在该脚步返回前添加必要的操作。
在上述 compile.sh 脚步最后的
此时,运行 compile.sh 脚步即可将该脚步中的 helloworld.tgz 还原并解压为 helloworld 目录,同时将中间文件 helloworld.tgz 删除,随后对 helloworld 进行编译。
首先,我们创建一个脚步用于解压 helloworld.tgz 文件:
该文件中需要注意几点:
__ARCHIVE_BELOW__ - 用于标识该文件中的压缩文件数据,即 helloworld.tgz 的数据,并且该行只能在文件的末尾。
awk - 用于查找 helloworld.tgz 数据的开始行。
tail - 用于解析 helloworld.tgz 的数据并利用管道传递给 tar 进行解压。
exit - mian() 函数中的 exit 命令是不可少的。如果没有该命令,shell 脚步会继续执行后面的内容导致出错。
接着,我们就将 helloworld.tgz 的数据放置在该文件之后,这样就可以实现脚步自解压编译了
完成上述步骤之后,我们就可以通过 shell-compile.sh 获取到 helloworld 目录,并对 helloworld 进行编译。
[2] Bash Self-Extracting Script
我目前了解到的 shell 自解压的安装脚步制作方式分为两种:
sharutils - 利用 sharutils 工具对多个文件进行归档,同时生成一个 shell 脚步用于取出这些文件。该脚步中包含编码后的二进制或压缩包等文件的信息以及解码操作。这种方式需要依赖于 sharutils 工具,不够灵活。
自己通过 shell 命名实现 - 这种方式几乎能在所有的 Linux 平台运行,不依赖于特定工具。
为了简化操作,我采用了一个简单的 helloworld 工程目录,然后利用脚步对其进行解压并对该工程进行编译来模拟安装。
$ tree helloworld helloworld/ main.c Makefile $ cat helloworld/main.c #include <stdio.h> int main() { printf("Hello world!\n"); return 0; } $ cat helloworld/Makefile .PHONY: all all: helloworld helloworld: main.o gcc -o $@ $^ %.o: %.c gcc -o $@ -c $< .PHONY: clean clean: rm -rf *.o helloworld
通过修改编译过程为安装过程即可实现脚步自动话安装。这里就只提供思路,不具体给出安装的示例了,希望大家可以举一反三。
Sharutils
Sharutils 是从许多文件中制作所谓的 shell 档案,准备通过电子邮件服务传输的工具。本文主要使用 shar 命令对多个文件进行归档,并调用其中的 shell 脚步执行基本的操作。在这之前需要首先安装 sharutils 工具集,在 Ubuntu 下使用如下命令:$ sudo apt-get install -y sharutils
首先,我们对 helloworld 进行压缩
$ tar -czvf helloworld.tgz helloworld helloworld/ helloworld/main.c helloworld/Makefile
接着我们使用 shar 对压缩包进行编码并重定向到 compile.sh 脚步中
$ shar helloworld.tgz > compile.sh shar: 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 arc 4000 hive, 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=true fi echo=echo save_IFS="${IFS}" IFS="${IFS}:" gettext_dir= locale_dir= set_echo=false for dir in $PATH do 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 fi done if ${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" fi fi IFS="$save_IFS" if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null then if (echo -n test; echo 1,2,3) | grep n >/dev/null then shar_n= shar_c=' ' else shar_n=-n shar_c= ; fi else shar_n= shar_c='\c' ; fi f=shar-touch.$$ st1=200112312359.59 st2=123123592001.59 st2tr=123123592001.5 # old SysV 14-char limit st3=1231235901 if 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 and installing GNU '\''touch'\'', distributed in GNU coreutils...' echo fi rm -f ${st1} ${st2} ${st2tr} ${st3} ${f} # if test ! -d ${lock_dir} ; then : else ${echo} "lock directory ${lock_dir} exists" exit 1 fi if mkdir ${lock_dir} then ${echo} "x - created lock directory ${lock_dir}." else ${echo} "x - failed to create lock directory ${lock_dir}." exit 1 fi # ============= 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.tgz M'XL(`+4CX%D``^W4STO#,!0'\%[W_HKGW&`35I-V:Z`;XG$7?UP%$4K6N6K6 MCJS#@_B_VQ9&"Z)#L,KP^SDT)0E)VO=>5K$QV4MFS>+<:8LH*#4I6ZDFHMGN M.=*72@A/"K^8)SU/*(<GK9VH8;?-(\OL/$6;)/UBWJ'Q([6JX[^.DM35+>Q1 M!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+G M>)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 ` end SHAR_EOF (set 20 17 10 13 10 23 22 'helloworld.tgz' eval "${shar_touch}") && \ chmod 0664 'helloworld.tgz' if test $? -ne 0 then ${echo} "restore of helloworld.tgz failed" fi if ${md5check} then ( ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'helloworld.tgz': 'MD5 check failed' ) << \SHAR_EOF 78be4fbc5349d5028fb6cac108fa39d5 helloworld.tgz SHAR_EOF else test `LC_ALL=C wc -c < 'helloworld.tgz'` -ne 344 && \ ${echo} "restoration warning: size of 'helloworld.tgz' is not 344" fi fi if rm -fr ${lock_dir} then ${echo} "x - removed lock directory ${lock_dir}." else ${echo} "x - failed to remove lock directory ${lock_dir}." exit 1 fi exit 0
从上面的 compile.sh 脚步中可以看到 shar 编码的文件信息。如果运行上面的 compile.sh 脚步,他只会将 helloworld.tgz 压缩包还原出来,若想要它自动编译,我们还需要在该脚步返回前添加必要的操作。
在上述 compile.sh 脚步最后的
exit 0前加入下面的内容:
echo "x - decompressing helloworld.tgz." tar -xf helloworld.tgz if test $? -ne 0 then echo "decompress helloworld.tgz failed" exit 1 fi # Remove helloworld.tgz and auto-compile helloworld echo "x - compiling helloworld" rm helloworld.tgz && cd helloworld && make if test $? -ne 0 then echo "compile helloworld failed" exit 1 fi
此时,运行 compile.sh 脚步即可将该脚步中的 helloworld.tgz 还原并解压为 helloworld 目录,同时将中间文件 helloworld.tgz 删除,随后对 helloworld 进行编译。
Shell 实现
该方式思想与 sharutils 相同,唯一不同的是 sharutils 对压缩包、二进制文件等可以采用不同的编码方式,而采用 shell 的实现则是直接将压缩包或二进制文件等写入到脚步中。这里我们同样采用 helloworld 来给出 shell 的实现方式。首先,我们创建一个脚步用于解压 helloworld.tgz 文件:
$ cat shell-compile.sh #!/bin/bash main() { 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 hell b272 oworld.tgz >> shell-compile.sh
完成上述步骤之后,我们就可以通过 shell-compile.sh 获取到 helloworld 目录,并对 helloworld 进行编译。
参考
[1] 在shell中嵌入二进制文件[2] Bash Self-Extracting Script
相关文章推荐
- 学习怎么开发shell安装脚本--freeswitch 安装
- Linux技术研究-基础篇(进程和shell及软件安装)
- windows下解压安装的mysql配置
- MySQL解压版(zip版)安装配置教程
- 安装版tomcat和解压版tomcat区别
- linux学习之(五)-linux文解压、压缩、安装
- postgresql 解压版在windows 安装
- mysql 5.5.x 解压版 安装
- Shell脚本源码编译安装MySQL5.1.73
- windows mysql 5.7.18 解压版安装配置过程
- [SHELL] LAMP一键安装脚本设计(v1,v2)
- mysql解压包的安装基础教程
- mysql最新通用二进制分发版本5.7.16自动安装shell脚本
- MySQL5.7.10解压版详细安装教程
- mysql系列-解压版安装mysql和配置以及密码修改
- CentOS安装zip和unzip进行压缩和解压
- mysql 5.7 zip解压版安装步骤
- MySQL 解压版/免安装版配置
- mysql5.6.11解压版安装
- Neo4j安装及使用shell脚本执行命令