使用shell脚本实现客户端应用自动化打包——mac
2017-12-27 16:40
871 查看
由于公司业务拓展,需要实现客户定制化,即自己上传必要的文件即可生成自己的安装包,这就需要实现自动化打包,打包脚本选择了shell脚本,可能会有人问为什么不用python呢?因为不会python啊
。
作为一个前端开发人员,让写自动化脚本,最开始还是一脸懵逼的,但是没办法啊,还是得硬着脸皮上啊,于是到网上找各种资料,学习了一下shell常用命令,然后便开始研究了,因为平时mac打包用的是package工具,所以得整理一下使用工具打包的过程是怎样的,然后再思考如何用脚本来替代工具所做的步骤。客户端开发的框架是用的nw.js+angular,所以得在nw.js的打包原理上入手。终于在github找到了开源项目nwjs-shell-builder。研究了一天脚本,然后就尝试着开始自己打包了。
首先需要做的就是配置文件config.json,该文件是配置打包时需要进行替换的相关信息
其中name字段是用来定义安装包的名称,applicationName是用来配置应用名称,version是用来配置应用版本,src表示的是源代码的路径,nwjsVersion表示的是nwjs的版本,osxIconPath表示的是应用图标,faviconIconPath表示的是任务栏图标,license表示的是用户许可协议,CFBundleIdentifier表示的bundleID,后面的则表示在应用中需要替换的样式,应用logo等。
接下来就是开始打包了,首先获取配置文件的路径,并根据配置文件中的key获取对应的value,定义临时打包文件夹,安装包存放位置,以下就是打包的脚本,给该脚本命名为package.sh
到这里为止,一个完整的打包脚本就出炉了,接下来就是执行脚本进行自动化打包了。其中具体的路径就需要我们根据自己的需要来进行配置了。进入到package.sh所在的文件目录,打开终端,执行命令./pack.sh --osx,接下来就坐等生成的pkg安装包了。第一次执行的时候会报错,直接加上chomd
+x package.sh,然后再执行就可以了。当然,能一下子把脚本贴出来肯定是在完全实现之后了,在研究过程中也是遇到很多很多各种各样的问题,毕竟是第一次接触shell,有时候甚至能在问题上卡住好久好久,不过好在结果是美好的。不过脚本肯定还有很多需要优化的地方,有什么建议或者问题也欢迎指正。
。
作为一个前端开发人员,让写自动化脚本,最开始还是一脸懵逼的,但是没办法啊,还是得硬着脸皮上啊,于是到网上找各种资料,学习了一下shell常用命令,然后便开始研究了,因为平时mac打包用的是package工具,所以得整理一下使用工具打包的过程是怎样的,然后再思考如何用脚本来替代工具所做的步骤。客户端开发的框架是用的nw.js+angular,所以得在nw.js的打包原理上入手。终于在github找到了开源项目nwjs-shell-builder。研究了一天脚本,然后就尝试着开始自己打包了。
首先需要做的就是配置文件config.json,该文件是配置打包时需要进行替换的相关信息
其中name字段是用来定义安装包的名称,applicationName是用来配置应用名称,version是用来配置应用版本,src表示的是源代码的路径,nwjsVersion表示的是nwjs的版本,osxIconPath表示的是应用图标,faviconIconPath表示的是任务栏图标,license表示的是用户许可协议,CFBundleIdentifier表示的bundleID,后面的则表示在应用中需要替换的样式,应用logo等。
接下来就是开始打包了,首先获取配置文件的路径,并根据配置文件中的key获取对应的value,定义临时打包文件夹,安装包存放位置,以下就是打包的脚本,给该脚本命名为package.sh
#!/usr/bin/env bash # Exit on error set -e BUILD_DIR=`pwd` WORKING_DIR="${BUILD_DIR}/TM 4000 P" RELEASE_DIR="${BUILD_DIR}/releases" DIST_DIR="${RELEASE_DIR}/build" # 配置文件config.json的路径 CONFIG_FILE="${BUILD_DIR}/config.json"
# 根据key获取value方法封装 get_value_by_key() { JSON_FILE=${CONFIG_FILE} KEY=${1} # REGEX="\"([^\"]*)\"" JSON_VALUE=$(cat ${JSON_FILE} | jq .${KEY} | sed 's/\"//g') echo "${JSON_VALUE}" } # Name of your package architechture="x64" # architechture="ia32" pack_osx () { for arch in ${architechture[@]}; do # 进入到TMP文件夹 cd ${WORKING_DIR} mkdir -p ${WORKING_DIR}/build_osx/root/Applications # 把app文件复制到applications中去/ cp -R "${WORKING_DIR}/osx-${arch}/latest-git/$(get_value_by_key applicationName).app" ${WORKING_DIR}/build_osx/root/Applications/ # 修改distribution.xml和componts.plist中的内容 cp ${BUILD_DIR}/resources/osx/components.plist ${RELEASE_DIR} cp ${BUILD_DIR}/resources/osx/distribution.xml ${RELEASE_DIR} #替换license中的应用名称 # cp ${BUILD_DIR}/resources/osx/License.rtf ${RELEASE_DIR} cp ${BUILD_DIR}/resources/osx/index.html ${RELEASE_DIR} sed -i.bak "s/PengCloud.app/$(get_value_by_key applicationName).app/g" ${RELEASE_DIR}/components.plist sed -i.bak "s/com.PengCloud.app/$(get_value_by_key CFBundleIdentifier)/g" ${RELEASE_DIR}/distribution.xml sed -i.bak "s/PengCloud.pkg/$(get_value_by_key name).pkg/g" ${RELEASE_DIR}/distribution.xml ( cd ${WORKING_DIR}/build_osx/root/Applications && chmod -R a+xr $(get_value_by_key applicationName).app ) local COUNT_FILES=$(find ${WORKING_DIR}/build_osx/root | wc -l) local INSTALL_KB_SIZE=$(du -k -s ${WORKING_DIR}/build_osx/root | awk '{print $1}') codesign -f --verbose=4 -s "Developer ID Application: Beijing Xiaopeng Education Technology Development Co. Ltd. (3QN2QHQC4Q)" ${WORKING_DIR}/build_osx/root/Applications/$(get_value_by_key applicationName).app --deep --timestamp=none pkgbuild --root ${WORKING_DIR}/build_osx/root/Applications/ --component-plist ${RELEASE_DIR}/components.plist --identifier $(get_value_by_key CFBundleIdentifier) --install-location /Applications ${RELEASE_DIR}/$(get_value_by_key name).pkg productbuild --distribution ${RELEASE_DIR}/distribution.xml --resources ${RELEASE_DIR} --package-path ${RELEASE_DIR}/ ${DIST_DIR}/$(get_value_by_key name)-$(get_value_by_key version).pkg productsign --sign "Developer ID Installer: Beijing Xiaopeng Education Technology Development Co. Ltd. (3QN2QHQC4Q)" ${DIST_DIR}/$(get_value_by_key name)-$(get_value_by_key version).pkg ${DIST_DIR}/$(get_value_by_key name)-$(get_value_by_key version)-sign.pkg --timestamp=none done; } build() { # if [[ `check_dependencies` = "NO" ]]; then # printf "\nNOTE! NSIS or ImageMagick is missing in the system\n\n"; # exit 1; # fi if [[ ! -f "${WORKING_DIR}" ]]; then mkdir -p TMP fi if [[ ! -d "${RELEASE_DIR}" ]]; then mkdir ${RELEASE_DIR} fi if [[ ! -d "${DIST_DIR}" ]]; then mkdir ${DIST_DIR} fi # 判断是否存在资源文件,如果不存在则下载 if [[ ! -d "$(get_value_by_key src)" ]]; then echo "=========bucunzai" git clone -b customized gitv:desktop $(get_value_by_key src) rm -rf ./resources/.git fi # 然后对资源文件中需要定制化的文件进行替换 # 替换应用图标 cp -rf $(get_value_by_key indexBackground) $(get_value_by_key src)/img/images/pengBG.png # 替换任务栏图标 cp -rf $(get_value_by_key faviconIconPath) $(get_value_by_key src)/configuration/favicon.png # 替换首页背景 cp -rf $(get_value_by_key indexBackground) $(get_value_by_key src)/img/images/pengBg.png # 替换首页logo cp -rf $(get_value_by_key indexLogo) $(get_value_by_key src)/img/images/pengLogo.png # 替换会议室背景 cp -rf $(get_value_by_key conferenceBackground) $(get_value_by_key src)/configuration/themes/default/background1.png # 替换package.json文件中的name和productName属性 sed -i "" 's/\("name": "\).*/\1'"$(get_value_by_key name)"'",/g' $(get_value_by_key src)/package.json # sed -i "" 's/\("productName": "\).*/\1'"$(get_value_by_key applicationName)"'",/g' $(get_value_by_key src)/package.json #替换中英文语言包中的应用名称 sed -i "" 's/\("IDS_PRODUCT_NAME": "\).*/\1'"$(get_value_by_key applicationName)"'",/g' $(get_value_by_key src)/configuration/languages/cn-cn.json sed -i "" 's/\("IDS_PRODUCT_NAME": "\).*/\1'"$(get_value_by_key name)"'",/g' $(get_value_by_key src)/configuration/languages/en-us.json ${BUILD_DIR}/nwjs-build.sh \ --name=$(get_value_by_key name) \ --application=$(get_value_by_key applicationName) \ --version=$(get_value_by_key version) \ --src=$(get_value_by_key src) \ --nw=$(get_value_by_key nwjsVersion) \ --osx-icon=$(get_value_by_key osxIconPath) \ --favicon-icon=$(get_value_by_key faviconIconPath) \ --CFBundleIdentifier=$(get_value_by_key CFBundleIdentifier) \ --indexBackground=$(get_value_by_key indexBackground) \ --indexLogo=$(get_value_by_key indexLogo) \ --conferenceBackground=$(get_value_by_key conferenceBackground) \ --target="${1}" \ --libudev \ --build cd ${BUILD_DIR} } clean() { if [[ ${1} = "all" ]];then rm -rf ${RELEASE_DIR}; printf "\nCleaned ${RELEASE_DIR}\n\n"; fi rm -rf ${WORKING_DIR}; printf "\nCleaned ${WORKING_DIR}\n\n"; } # TODO maybe deal with cmd switches or leave it all in the config.json file if [[ ${1} = "--osx" ]]; then clean "all"; build "5"; pack_osx; fi
我将生成.app文件的脚本分离出来了,命名为nwjs-build.sh,内容如下:
#!/usr/bin/env bash WORKING_DIR="$(cd -P -- "$(dirname -- "$0")" && pwd -P)" # default is "FALSE" LOCAL_NW_ARCHIVES_MODE=true LOCAL_NW_ARCHIVES_PATH="${WORKING_DIR}/nwjs_download_cache" # Default nwjs version NW_VERSION="0.23.7" # Base domain for nwjs download server DL_URL="http://dl.nwjs.io" # This directory will be auto created TMP="TMP" # Build target(s) # 0 - linux-ia32 # 1 - linux-x64 # 2 - win-ia32 # 3 - win- # 4 - osx-ia32 # 5 - osx-x64 TARGET="0 1 2 3 4 5" # Final output directory (relative to current directory where this script running from) RELEASE_DIR="${WORKING_DIR}/${TMP}/output" # Date on the package archive as PkgName-YYYYMMDD-OS-architecture.zip DATE=$(date +"%Y%m%d") # Name of your package # Package version # Handle libudev on linux LIBUDEV_HANDLER=false ARR_OS[0]="linux-ia32" ARR_OS[1]="linux-x64" ARR_OS[2]="win-ia32" ARR_OS[3]="win-x64" ARR_OS[4]="osx-ia32" ARR_OS[5]="osx-x64" ARR_DL_EXT[0]="tar.gz" ARR_DL_EXT[1]="tar.gz" ARR_DL_EXT[2]="zip" ARR_DL_EXT[3]="zip" ARR_DL_EXT[4]="zip" ARR_DL_EXT[5]="zip" ARR_EXTRACT_COMMAND[0]="tar" ARR_EXTRACT_COMMAND[1]="tar" ARR_EXTRACT_COMMAND[2]="zip" ARR_EXTRACT_COMMAND[3]="zip" ARR_EXTRACT_COMMAND[4]="zip" ARR_EXTRACT_COMMAND[5]="zip" TXT_BOLD="\e[1m" TXT_NORMAL="\e[1m" TXT_RED="\e[31m" TXT_BLUE="\e[34m" TXT_GREEN="\e[32m" TXT_YELLO="\e[93m" TXT_RESET="\e[0m" TXT_NOTE="\e[30;48;5;82m" usage() { cat <<EOF LICENSE MIT $(cat ${WORKING_DIR}/LICENSE) EOF } NOTE () { printf "\n"; printf "${TXT_NOTE} ${1} ${TXT_RESET} " printf "\n"; } upper_case_word() { word=${1} therest=$(tr '[a-z]' '[A-Z]'<<<"${word:0:1}") echo "${therest}${word:1}" } clean() { rm -rf ${WORKING_DIR}/${TMP}; NOTE "Removed \"${WORKING_DIR}/${TMP}\" directory and it's content"; } extractme() { if [[ ${1} = "zip" ]]; then unzip -qq ${2} -d ${3}; else tar xzf ${2} -C ${3}; fi } split_string() { #USAGE: `split_string $string ,` - the comma here is the separator. Also see `man cut` echo "$1" | cut -d"$2" -f1; } make_bins() { # 创建一个release文件夹 mkdir -p ${RELEASE_DIR} local make_os=`split_string "${1}" "-"` echo "========ddd++++++${1}" if [[ ${make_os} = "win" ]]; then mk_windows ${1}; elif [[ ${make_os} = "osx" ]]; then mk_osx ${1}; else printf "\nNo such target\n"; exit 1; fi } mk_osx() { cp -R ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/nwjs/*.app ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git/${APPLICATION_NAME}.app; cp -R ${WORKING_DIR}/${TMP}/osx-x64/latest-git/${APPLICATION_NAME}.nw ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git/${APPLICATION_NAME}.app/Contents/Resources/app.nw; rm -r ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git/${APPLICATION_NAME}.nw if [[ -f "${OSX_RESOURCE_ICNS}" ]];then cp -r ${OSX_RESOURCE_ICNS} ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git/${APPLICATION_NAME}.app/Contents/Resources/ else OSX_RESOURCE_ICNS="${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/nwjs/node-webkit.app/Contents/Resources/nw.icns" fi ICON_NAME=$(echo "${OSX_RESOURCE_ICNS}" | rev | cut -d"/" -f1 | rev) sed -i.bak "s/app.icns/${ICON_NAME}/g" ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git/${APPLICATION_NAME}.app/Contents/Info.plist sed -i.bak "s/io.nwjs.nwjs/${CFBundleIdentifier}/g" ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git/${APPLICATION_NAME}.app/Contents/Info.plist sed -i.bak "s/3071.115/${PKG_VERSION}/g" ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git/${APPLICATION_NAME}.app/Contents/Info.plist rm ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git/${APPLICATION_NAME}.app/Contents/Info.plist.bak cd ${WORKING_DIR}/${TMP}/${1}/latest-git zip -qq -r ${APPLICATION_NAME}-${DATE}-${1}.zip *; mv ${APPLICATION_NAME}-${DATE}-${1}.zip ${RELEASE_DIR}; cd ${WORKING_DIR}; } build() { for i in ${TARGET}; do mkdir -p ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git mkdir -p ${LOCAL_NW_ARCHIVES_PATH} NOTE 'WORKING' printf "Bulding ${TXT_BOLD}${TXT_YELLO}${APPLICATION_NAME}${TXT_RESET} for ${TXT_BOLD}${TXT_YELLO}${ARR_OS[$i]}${TXT_RESET}\n" # 这里遍历之后为什么是上层文件夹目录 # for DL_FILE in ${LOCAL_NW_ARCHIVES_PATH}/nwjs-sdk-v${NW_VERSION}-${ARR_OS[$i]}.${ARR_DL_EXT[$i]}; do for DL_FILE in ${LOCAL_NW_ARCHIVES_PATH}/*-v${NW_VERSION}-${ARR_OS[$i]}.${ARR_DL_EXT[$i]}; do printf "File ${TXT_YELLO}nwjs-${NW_VERSION}-${ARR_OS[$i]}.${ARR_DL_EXT[$i]}${TXT_RESET} is in the download cache\n- no need to re-download\n" cp ${LOCAL_NW_ARCHIVES_PATH}/nwjs-sdk-v${NW_VERSION}-${ARR_OS[$i]}.${ARR_DL_EXT[$i]} ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}; # ARR_EXTRACT_COMMAND:zip extractme这个方法的作用是解压文件放到指定目录,第一个参数是压缩文件的格式,第二个参数是压缩文件,第三个参数是压缩后放置的位置 extractme "${ARR_EXTRACT_COMMAND[$i]}" "${DL_FILE}" "${WORKING_DIR}/${TMP}/${ARR_OS[$i]}"; # mkdir -p ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/nwjs mv ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/*-v${NW_VERSION}-${ARR_OS[$i]} ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/nwjs; # # 如果是mac系统,将自己的代码拷贝到.nw文件夹中 if [[ `split_string "${ARR_OS[$i]}" "-"` = "osx" ]]; then cp -r ${PKG_SRC} ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git/${APPLICATION_NAME}.nw; else # 如果不是,将自己的代码压缩放到.nw文件夹中 cd ${PKG_SRC}; zip -qq -r ${APPLICATION_NAME}.zip *; mv ${APPLICATION_NAME}.zip ${WORKING_DIR}/${TMP}/${ARR_OS[$i]}/latest-git/${APPLICATION_NAME}.nw; cd ${WORKING_DIR}; fi # Build binaries make_bins "${ARR_OS[$i]}"; done done NOTE "DONE"; printf "You will find your '${APPLICATION_NAME}' builds in '${RELEASE_DIR}' directory\n"; } ### Arguments while true; do case $1 in -h | --help ) clear > /dev/null; usage | less; exit 0 ;; --nw=* ) NW_VERSION="${1#*=}"; shift ;; --name=* ) PKG_NAME="${1#*=}"; shift ;; --application=* ) APPLICATION_NAME="${1#*=}"; shift ;; --version=* ) PKG_VERSION="${1#*=}"; shift ;; --output-dir=* ) RELEASE_DIR="${1#*=}"; shift ;; --src=* ) PKG_SRC="${1#*=}" shift ;; --target=* ) TARGET="${1#*=}" shift ;; --osx-icon=* ) OSX_RESOURCE_ICNS="${1#*=}" shift ;; --favicon-icon=* ) OSX_FAVICON="${1#*=}" shift ;; --CFBundleIdentifier=* ) CFBundleIdentifier="${1#*=}" shift ;; --indexBackground=* ) indexBackground="${1#*=}" shift ;; --indexLogo=* ) indexLogo="${1#*=}" shift ;; --conferenceBackground=* ) conferenceBackground="${1#*=}" shift ;; --clean ) clean; exit 0 ;; --local ) LOCAL_NW_ARCHIVES_MODE=true shift ;; --libudev ) LIBUDEV_HANDLER=true shift ;; --build ) build; exit 0 ;; -- ) shift; break ;; -* ) printf 'Hmmm, unknown option: "%s".\n' "${1}"; exit 0 ;; * ) usage; break ;; esac done
到这里为止,一个完整的打包脚本就出炉了,接下来就是执行脚本进行自动化打包了。其中具体的路径就需要我们根据自己的需要来进行配置了。进入到package.sh所在的文件目录,打开终端,执行命令./pack.sh --osx,接下来就坐等生成的pkg安装包了。第一次执行的时候会报错,直接加上chomd
+x package.sh,然后再执行就可以了。当然,能一下子把脚本贴出来肯定是在完全实现之后了,在研究过程中也是遇到很多很多各种各样的问题,毕竟是第一次接触shell,有时候甚至能在问题上卡住好久好久,不过好在结果是美好的。不过脚本肯定还有很多需要优化的地方,有什么建议或者问题也欢迎指正。
相关文章推荐
- 使用shell脚本实现php应用的批量更新
- 自动化运维-使用Shell脚本简单实现
- 使用shell脚本自动化安装Nagios服务器端和客户端
- 使用shell脚本实现自动化部署hadoop集群
- 使用shell脚本自动化安装zabbix客户端
- iOS自动化编译打包提交-Shell脚本实现
- 详解Shell脚本实现iOS自动化编译打包提交
- 一部Web应用自动化部署的进化史[AWS]-使用shell实现CodeDeploy
- iOS 自动化打包发布测试平台后邮件通知测试人员(在Mac使用Python脚本发送邮件)
- 使用Shell脚本实现自动化静默安装Oracle软件
- 一部Web应用自动化部署的进化史[AWS]-使用shell实现CodeDeploy
- iOS开发-ipa打包终极教程-使用终端和shell脚本实现
- 使用shell脚本实现自动化部署HBASE集群
- Mac 上使用 Shell 脚本 + adb shell 实现简单的 Android 模拟点击自动化测试
- 详解Shell脚本实现iOS自动化编译打包提交
- 使用 Perl 脚本实现交互式命令行程序的管理与测试自动化
- asp.net2.0中使用客户端回调实现无刷新应用!
- 使用linux的shell脚本实现在当前行重复动态显示时间等字符串信息(不另起新行)
- 使用 Perl 脚本实现交互式命令行程序的管理与测试自动化
- 用Shell脚本实现自动化完成属于自己的微型Linux!(一)