Linux系统bin文件打包方法

  • 最近的项目需要客户端从服务器获取到文件后自动执行;由于可执行程序中有相关配置文件,并且运行前要进行环境变量的配置,所以不能直接下载可执行程序运行,上网搜了一下解决方法,发现可以打成bin包,下载时下载这个bin文件,然后运行,先进行解包安装,然后再脚本里配置环境变量,最后运行程序;

  • bin包的制作需要三步:1、 编写shell脚本文件; 2、 对可执行程序及相关文件进行打包压缩; 3、 使用cat命令把这两个文件封装成一个bin安装包;

  • 最后生成的bin文件是一个前半部分为shell脚本文件,后半部分为二进制压缩包文件的文件;我们直接运行这个bin文件,会首先执行前半部分的脚本,所以我们需要再脚本里编写程序把后半部分的压缩包分解出来,并进行解压和运行;

一、 编写shell脚本;

  • 脚本文件主要功能是把cat命令打包进bin文件中的二进制压缩包分离出bin文件,并进行解压;分离操作可以用两种方法来做:sed命令和tail命令
  • 1、 使用sed命令
    sed -n -e '1,/^exit 0$/!p' $0 >xxx.tgz 2>/dev/null
    2、 使用tail命令
    tail +$lines $0 >xxx.tgz
    注:但是使用中发现第一种方法并不能成功分离出压缩文件,不知道什么原因,研究了一下午也没解决,对比cat封装前的压缩包和分离出来的压缩包,发现文件大小是一样的,我用diff命令对比两个文件,发现两个文件并不一样,最后用vi打开两个文件对比,发现分离后的压缩包里面多了很多换行;
  • 我的install.sh 文件模板
#!/bin/bash
lines=186
flag=$1
force_upgrade=$2
workdir=$(cd $(dirname $0); pwd)
mkdir -p $workdir/temp >/dev/null 2>&1
tmp_dir=$workdir/temp
red_echo() { echo -e "\033[031;1m$@\033[0m"; }
fail () {
   # 打印错误消息,并以非0值退出程序
   # 参数1: 消息内容
   # 参数2: 可选, 返回值, 若不提供默认返回1
   local timestamp=$(date +%Y%m%d-%H%M%S)
   local level=FATAL
   local retval=${2:-1}
   local func_seq=$(echo ${FUNCNAME[@]} | sed 's/ /-/g')
   local logfile=${LOG_FILE:=/tmp/o2d.log}

   echo "$timestamp $BASH_LINENO   $(red_echo $@)"
   echo "$timestamp $level|$BASH_LINENO|${func_seq} $@" >> $logfile
   echo "===================process interrupted, exited==================="
   exit $retval
}

# 环境检查
function check_dir_space() {
  path=$1
  space=$2
  space_size=$(df -k "$path" | awk 'NR == 1 {next} {print $4}')
  space_size=$((space_size / 1024 / 1024))

  if [ $space_size -lt $space ]; then
    fail "当前目录($path)空间为: ${space_size}GB,不足${space}GB,无法进行安装。"
  fi
}

show_spinner()
{
    $* &
    PID=$!
    local delay=0.1
    local spinstr='|/-\'
    spin[0]="-"
    spin[1]="\\"
    spin[2]="|"
    spin[3]="/"
    sleep 0.05
    if [[ "$flag" == "install" ]];then
        echo -n "开始产品安装准备... "
    elif [[ "$flag" == "upgrade" ]]; then
        echo -n "开始产品升级准备... "
    elif [[ "$1" == "unzip" ]]; then
        echo -n "正在进行解压... "
    else
        echo ""
    fi
    while kill -0 $PID 2>/dev/null
    do
        for i in "${spin[@]}"
            do
                echo -ne "$i"
                sleep 0.1
                echo -ne "\b"
        done

    done
    echo -e "$(tput setaf 2)PASS$(tput sgr0)"
}

function readINI() {
  INIFILE=$1
  SECTION=$2
  ITEM=$3
  _readIni=$(awk -F '=' '/\['$SECTION'\]/{a=1}a==1&&$1~/'$ITEM'/{print $2;exit}' $INIFILE)
  echo ${_readIni}
}

function pre_install(){
   rm -rf ${tmp_dir}/O2D_Controller.tar.xz
   rm -rf ${tmp_dir}/dr_controller
   temptar=${tmp_dir}/O2D_Controller.tar.xz
   tail -n +$lines $0 > ${temptar}
   tar xvf ${temptar} -C ${tmp_dir} >/dev/null 2>&1
}

parse_json() {
    local json=$1
    # \"inet\":\s*\" 匹配 "inet": ", \" 匹配末尾, ([^"]+) 匹配ip
    local regex='\"inet\":\s*\"([^"]+)\"'
    while [[ $json =~ $regex ]]; do
        local ip=${BASH_REMATCH[1]}
        inet_array+=("$ip")
        # #* 表示从变量的开头开始,删除第一个匹配的子字符串 "\"inet\": \"$ip\"" 及其之前的内容
        json=${json#*"\"inet\": \"$ip\""}
    done
}

function install_alone() {
   show_spinner pre_install
   # 切换路径,否则执行drcontroller会报错
   workpath=${tmp_dir}/dr_controller
   config_file=${workpath}/server.ini
   cd $workpath
   if [[ $flag = install ]]; then
     # 获取机器上的所有网卡信息
     ${workpath}/netcardmgr -s
     echo "当前主机ip信息如下:"
     echo ""
     json=`cat /usr/local/.one2data_netinfo.json`
     inet_array=()
     parse_json "$json"
     count=${#inet_array[@]}
     for ((i =0; i<count; i++)); do
         echo "[$i] ${inet_array[$i]}"
     done
     # 用户选择网卡
     valid_input=false
     while [[ $valid_input == false ]]; do
         read -p "请选择管理网ip对应的编号: " choice
         echo ""
         if [[ $choice =~ ^[0-9]+$ ]]; then
             if (( choice >= 0 && choice < count )); then
                 valid_input=true
             else
                 echo "无效的编号,请重新输入."
             fi
         else
             echo "无效的输入,请输入一个有效的编号."
         fi
     done
     selected_ip=${inet_array[$choice]}
     echo "您选择的管理网IP为: $selected_ip"
     echo ""
     #请输入你的安装目录
     read -p "请输入产品安装目录(输入回车键将采取默认目录进行安装):" dir
     echo ""
     if [ -z "$dir" ]; then
        install_dir=$(readINI $config_file install home_path)
        echo "采取默认目录: ${install_dir} 进行安装:"
        sed -i -e "s|controller_ip=|controller_ip=${selected_ip}|g" $config_file
        ./drcontroller.sh install
     else
       #通过sed命令将server.ini中对应的配置项进行修改
       sed -i -e "s|controller_ip=|controller_ip=${selected_ip}|g" -e "s|home_path=.*$|home_path=${dir}|g" $config_file
       #配置项修改完成以后通过以下方式进行安装
        ./drcontroller.sh install
     fi
   else
      ./drcontroller.sh upgrade $force_upgrade
   fi
   rm -rf ${tmp_dir}
   rm -rf ${tmp_dir}

}

function unzip() {
   temptar=${tmp_dir}/O2D_Controller.tar.xz
   tail -n +$lines $0 > ${temptar}
   tar xvf ${temptar} >/dev/null 2>&1
   rm -rf ${tmp_dir}
}

check_dir_space $workdir 10
case "$1" in
install)
   install_alone
   exit 0
   ;;
 unzip)
   show_spinner unzip
   exit 0
   ;;
 upgrade)
   install_alone
   exit 0
   ;;
*)
  echo "Usage:   $0 { install | unzip | upgrade }" >&2
  echo "install: install product."
  echo "unzip:   unzip product"
  echo "upgrade: upgrade product"
  RETVAL=1
  exit $RETVAL
  ;;
esac

二、对可执行程序进行打包
新建一个目录,把运行需要的所有文件拷贝进去,然后使用tar命令进行打包:
tar -czvf qoe.tgz qoe/

三、使用cat命令封装为bin
cat install.sh qoe.tgz > qoe.bin

最后完成
chmod +x test.bin
测试
./test.bin

参考链接
  • https://www.jianshu.com/p/9f2919484317

  • https://blog.csdn.net/jswawawa/article/details/72318024?locationNum=3&fps=1

  • https://blog.csdn.net/lien0906/article/details/52689185

  • https://www.cnblogs.com/slz-coder150315/p/9415463.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值