shell脚本中嵌入文件工具

#!/bin/bash
###
 # @Author: huangjinbang
 # @AuthorEmail: huangjinbang1996@163.com
 # @Date: 2023-11-12 18:52:45
 # @LastEditors: huangjinbang 
 # @LastEditorsEmail: huangjinbang1996@163.com
 # @LastEditTime: 2024-12-19 16:49:43
 # @FilePath: shell脚本中嵌入文件工具.sh
 # @Description: 
 # Copyright (c) 2024 by ${git_name} email: ${git_email}, All Rights Reserved.
### 

#记得看看sh的软链接 /bin/sh link dash  or /bin/sh link bash
# 来源主体:https://www.wpon.cn/12009.html
# 第一功能:1.读取文件加载到本脚本当中,2.清理脚本;注意文件尾部有时候会重复,不要重复

#################################################################
#  default默认设置脚本环境设置,可以引入下
set +a
export LANG=en_US.utf8
export LANGUAGE='en_US:en'
curPath=$(readlink -f "$(dirname "$0")")    # 获取文件所在文件夹绝对路径(或当鼠标点击文件运行的时候)
#记录本脚本名
curScript=$0

# 开启调试模式
if [ ".$1" = ".--debug" ]; then
    shift
    # 设置 PS4 显示行号,$LINENO 表示当前行号
    export PS4='+${LINENO}: '
    set -x
fi
if [ ".$1" = ".-v" ] || [ ".$1" = ".--version" ]; then
    echo "test version"
    exit 0
fi
# while getopts 's:' OPT;do
#     case "${OPT}" in 
#         "r") echo rrrr ;;
#         "d") echo dddd ;;
#         "h") echo "here is help";help ;;
#         "?") echo "here is ?";help ;;
#     esac
# done
#################################################################

#文件BIN,base64 -d解码后,源文件原名
__BIN_FILE_NAME__=
#记录源文件md5
__BIN_FILE_MD5__=
#是否为文件夹
__BIN_FILE_IS_DIR__=dir

# ###1.检查sh是否导入文件,2.检查导入的有无文件名记录,3.校验md5
__GET_BIN_FILE_BEGIN_STRING__=`(awk '/^__BIN_FILE_BEGIN__/{print NR}' "${curScript}" )` 
__GET_BIN_FILE_BEGIN_STRING__=$(($__GET_BIN_FILE_BEGIN_STRING__+1))
# echo $__GET_BIN_FILE_BEGIN_STRING__
string=`(sed  -n ''"$__GET_BIN_FILE_BEGIN_STRING__"',$p' "${curScript}")`
#是否压缩
__SET_ZIP__=1

help() {
    echo "Usage:"
    echo "${curScript} [-r file] [-d]"
    echo "Description:"
    echo "
	功能一:
    1.无参数时,执行,前提改好脚本哈
	功能二:
    2.-r file压入文件,__BIN_FILE_BEGIN__记得这行有下一行,
    3. -d 清除添加了的文件"
    exit 1
}

check_bin_file_have(){
    # echo "${string}"
    if [ ! -z "${string}" ];then
        echo "__BIN_FILE_BEGIN__\n有导入文件,未导入要导入文件;或者清理后重新导入"
        exit
    fi
}

targz(){
    check_bin_file_have
    # 1.base64
    # 记录readfilename(__BIN_FILE_NAME__)
    sed -i 's#^__BIN_FILE_NAME__.*#__BIN_FILE_NAME__="'"""$1"""'"#g' "${curScript}"
    if [ ! -d "$1" ];then
        # 记录MD5(__BIN_FILE_MD5__)
        filemd5=`(/usr/bin/md5sum "$1" | awk '{print $1}')`
        sed -i "s#^__BIN_FILE_MD5__.*#__BIN_FILE_MD5__=${filemd5}#g" "${curScript}"
        #清空文件夹标识
        sed -i "s#^__BIN_FILE_IS_DIR__.*#__BIN_FILE_IS_DIR__=#g" "${curScript}"
    else 
        sed -i "s#^__BIN_FILE_IS_DIR__.*#__BIN_FILE_IS_DIR__=dir#g" "${curScript}"
    fi
    if [ $__SET_ZIP__ -eq "0" ];then
        #不压缩
        base64 "$1" >> "${curScript}"
    else
        #zip压缩
        zip -9rq archive$$.zip "$1"
        base64 archive$$.zip >> "${curScript}"
        rm archive$$.zip
    fi
    # allfilename[${#allfilename[*]}]="$1"
    exit 0
}

deletedata(){
    # sed匹配一行,保留匹配的行,并删除匹配目标的下一行至末尾行;注:bug,有时清除多了会重复__BIN_FILE_BEGIN__记得删掉
    echo "deletdata"
    # 方法一:注:bug,有时清除多了会重复__BIN_FILE_BEGIN__记得删掉
    # sed -i '/^__BIN_FILE_BEGIN__/{p;:a;N;$!ba;d}' "${curScript}" 
    # 方法二:查找第一个匹配,记录行数n,删除n+1,$行
    grep_num=`(grep -n -m 1 "^__BIN_FILE_BEGIN__" "${curScript}" |awk -F ':' '{print $1}')`
    grep_num=$(($grep_num+1))
    echo __BIN_FILE_BEGIN__:$grep_num
    sed -i ''''$grep_num''',$d' "${curScript}"
    # 清空name  MD5
    sed -i "s#^__BIN_FILE_NAME__.*#__BIN_FILE_NAME__=#g" "${curScript}"
    sed -i "s#^__BIN_FILE_MD5__.*#__BIN_FILE_MD5__=#g" "${curScript}"
    exit 0
}

###bash内置命令
while getopts 'r: h d s' OPT;do
    case "${OPT}" in 
        "s") __SET_ZIP__=0;;
        "r") targz "${OPTARG}" ;;
        "d") deletedata ;;
        "h") echo "here is help";help ;;
        "?") echo "here is ?";help ;;
    esac
done
######################################################################

check_bin(){
    # echo "${string}"
    if [ -z "${string}" ];then
        echo "__BIN_FILE_BEGIN__\n无导入文件"
        help
        exit 1
    elif [ -z "${__BIN_FILE_NAME__}" ];then
        echo "__BIN_FILE_NAME__为空"
        # help
    elif [ ! -z "${__BIN_FILE_NAME__}" ];then
        echo '原导入为文件夹:)'
    elif [ -z "${__BIN_FILE_MD5__}" ];then
        echo "__BIN_FILE_MD5__为空"
        help
        exit 3
    fi
}
check_bin

#  第二功能,执行脚本:预处理环境,解压,校验,安装,安装后执行;像不像软件安装包流程?更多的可以操作下边代码
# tmp_install_dir=

pre_install(){

    echo "准备安装环境(略)..."

    mkdir ./install.tmp.$$

}

check_sum(){
    if [ -x /usr/bin/md5sum ]&&[ -f "install.tmp.$$/${__BIN_FILE_NAME__}" ]; then
        echo "正在检查md5......"
        sum_tmp=`(/usr/bin/md5sum install.tmp.$$/"${__BIN_FILE_NAME__}" | awk '{print $1}')`
        echo "$sum_tmp"
        echo "${__BIN_FILE_MD5__}"
        if [ "$sum_tmp" != "${__BIN_FILE_MD5__}" ]; then
            echo "文件md5不一致,请检查文件完整性,退出!"
            exit 1
        fi
    else
        echo "找不到md5sum命令或文件未提取,退出"
        exit 1

    fi
}

extract(){
    echo "从脚本中提取文件"
    # #二进制文件BIN换行
    line_number=`awk '/^__BIN_FILE_BEGIN__/ {print NR + 1; exit 0; }' "${curScript}"`    
    # # 1.直接输出
    # tail -n +$line_number "$0" >./install.tmp.$$/extract.$$
    # # 2.base64解压
    tail -n +$line_number "${curScript}" >./install.tmp.$$/extract_tmp.$$
    
    # # 3.解压压缩包
    if [ $__SET_ZIP__ -eq 0 ];then
        #不压缩
        base64 -d ./install.tmp.$$/extract_tmp.$$ >./install.tmp.$$/"${__BIN_FILE_NAME__}"
        echo base64output
    else
        #zip压缩
        base64 -d ./install.tmp.$$/extract_tmp.$$ >./install.tmp.$$/archive$$.zip
        unzip -oq ./install.tmp.$$/archive$$.zip -d ./install.tmp.$$/
        rm ./install.tmp.$$/archive$$.zip
    fi
}

install(){

    echo "安装中(略)..."

}

post_install(){

    echo "配置中(略)..." 

    echo "清理临时文件"

    # rm -rf install.tmp.$$
    rm -f install.tmp.$$/extract_tmp.$$

}



main(){

    pre_install

    extract

    install

    post_install

    exit 0
}

main









#这行下面接二进制文件BIN换行;若有时MD5校验不对,确认__BIN_FILE_BEGIN__是不是唯一一行且下一行是空行
# TODO: 有时-d删的,删完会增多,待解决
__BIN_FILE_BEGIN__

posted @ 2024-12-19 16:53  ThreeFlower  阅读(45)  评论(0)    收藏  举报