-
最近的项目需要客户端从服务器获取到文件后自动执行;由于可执行程序中有相关配置文件,并且运行前要进行环境变量的配置,所以不能直接下载可执行程序运行,上网搜了一下解决方法,发现可以打成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