diff --git a/wu-lazy-cloud-heartbeat-start/wu-lazy-cloud-heartbeat-client-start/install.sh b/wu-lazy-cloud-heartbeat-start/wu-lazy-cloud-heartbeat-client-start/install.sh new file mode 100644 index 00000000..469141c4 --- /dev/null +++ b/wu-lazy-cloud-heartbeat-start/wu-lazy-cloud-heartbeat-client-start/install.sh @@ -0,0 +1,414 @@ +#!/bin/bash +set -e + +# 异常日志文件路径 +ERROR_LOG_FILE="packaging_error.log" + +####################################### +# 配置参数 - 仅在此处修改参数值 +####################################### +APP_NAME="wlcn-client" +APP_VERSION="1.0.0" +MAIN_CLASS="org.framework.lazy.cloud.network.heartbeat.client.LazyCloudHeartbeatClientStart" +ICON_FILE="src/main/resources/app.icns" +# 修复变量名拼写错误:OUTPUTPUT_BASE -> OUTPUT_BASE +OUTPUT_BASE="./build" +JDK_HOME=${JAVA_HOME} +####################################### + +# 派生路径 +JRE_DIR="${OUTPUT_BASE}/myjre" +OUTPUT_DIR="${OUTPUT_BASE}/dist" +MAIN_JAR="" # 初始化主JAR路径变量 +MODULES="" + +# 函数:去除路径末尾的斜杠 +trim_trailing_slash() { + local path="$1" + # 若路径非空且以/结尾,则去除末尾的/ + if [ -n "$path" ] && [ "${path: -1}" = "/" ]; then + echo "${path%/}" + else + echo "$path" + fi +} + +# 函数:记录错误日志并退出 +error_exit() { + local error_message="$1" + local timestamp=$(date +"%Y-%m-%d %H:%M:%S") + + # 输出到控制台 + echo -e "\033[0;31m错误: $error_message\033[0m" >&2 + + # 记录到日志文件 + echo "[$timestamp] 错误: $error_message" >> "$ERROR_LOG_FILE" + echo "[$timestamp] 脚本异常退出" >> "$ERROR_LOG_FILE" + echo "----------------------------------------" >> "$ERROR_LOG_FILE" + + # 退出脚本 + exit 1 +} + +# 函数:在指定目录中查找JAR文件并赋值给MAIN_JAR +find_jar_in_directory() { + local dir="$1" + + # 检查目录是否存在 + if [ ! -d "$dir" ]; then + echo "错误:目录 '$dir' 不存在" + return 1 + fi + + # 查找目录中的JAR文件(兼容写法) + local valid_jars=() + for jar in $(ls -1 "$dir"/*.jar 2>/dev/null); do + if [ -f "$jar" ]; then + valid_jars+=("$jar") + fi + done + + # 检查JAR文件情况 + if [ ${#valid_jars[@]} -eq 0 ]; then + echo "错误:在目录 '$dir' 中未找到任何JAR文件" + return 1 + elif [ ${#valid_jars[@]} -gt 1 ]; then + echo "错误:在目录 '$dir' 中找到多个JAR文件:" + for jar in "${valid_jars[@]}"; do + echo " - $(basename "$jar")" + done + return 1 + else + # 找到唯一JAR文件,赋值给全局变量MAIN_JAR + MAIN_JAR="${valid_jars[0]}" + echo "找到JAR文件:$MAIN_JAR" + return 0 + fi +} + +# 函数:获取JAR文件,支持用户指定目录(带Tab补全) +get_main_jar() { + local valid_jars=() + + # 过滤出当前目录中有效的JAR文件(兼容写法) + for jar in $(ls -1 *.jar 2>/dev/null); do + if [ -f "$jar" ]; then + valid_jars+=("$jar") + fi + done + + # 如果当前目录找到唯一JAR文件,直接赋值 + if [ ${#valid_jars[@]} -eq 1 ]; then + MAIN_JAR="${valid_jars[0]}" + echo "当前目录找到JAR文件:$MAIN_JAR" + return 0 + fi + + # 处理多个JAR文件的情况 + if [ ${#valid_jars[@]} -gt 1 ]; then + local jar_list="" + for jar in "${valid_jars[@]}"; do + jar_list+=" - $(basename "$jar")\n" + done + error_exit "当前目录下找到多个JAR文件,请保留唯一主JAR文件后重试:\n$jar_list" + fi + + # 当前目录未找到JAR文件,提示用户输入目录(支持Tab补全) + echo "当前目录下未找到任何JAR文件。" + local jar_dir="" + local trimmed_dir="" + + while true; do + # 使用read -e启用Tab键路径补全 + read -e -p "请输入包含JAR文件的文件夹路径(相对路径,按Tab键可补全): " jar_dir + + # 处理用户输入的路径(去除末尾斜杠) + trimmed_dir=$(trim_trailing_slash "$jar_dir") + + if [ -z "$trimmed_dir" ]; then + echo "路径不能为空,请重新输入" + continue + fi + + # 尝试查找JAR文件并赋值给MAIN_JAR + if find_jar_in_directory "$trimmed_dir"; then + # 查找成功,MAIN_JAR已被赋值 + return 0 + fi + done +} + +# 函数:初始化参数数组(使用两个索引数组替代关联数组) +init_parameters() { + # 参数名称数组 + local names=( + "应用名称" + "版本号" + "主类全路径" + "主JAR文件" + "图标文件" + "输出目录" + "JDK安装路径" + "自定义JRE目录" + ) + + # 参数值数组(与名称数组顺序对应) + local values=( + "$APP_NAME" + "$APP_VERSION" + "$MAIN_CLASS" + "$MAIN_JAR" + "$ICON_FILE" + "$OUTPUT_DIR" + "$JDK_HOME" + "$JRE_DIR" + ) + + # 返回两个数组(通过字符串拼接传递) + echo "${names[*]}|||${values[*]}" +} + +# 函数:显示参数表格 +display_parameters() { + local params_str="$1" + # 拆分参数数组 + local names_str="${params_str%%|||*}" + local values_str="${params_str#*|||}" + + # 转换为数组 + local names=($names_str) + local values=($values_str) + + # 计算最长参数名长度 + local max_len=0 + for name in "${names[@]}"; do + local len=${#name} + if (( len > max_len )); then + max_len=$len + fi + done + + local term_width=$(tput cols 2>/dev/null || echo 80) + local line=$(printf "%0.s-" $(seq 1 $term_width)) + + echo -e "\n===== 打包参数信息 =====" + echo "$line" + printf "| %-${max_len}s | %s |\n" "参数名称" "参数值" + echo "$line" + + # 遍历输出所有参数(使用索引对应) + for ((i=0; i<${#names[@]}; i++)); do + printf "| %-${max_len}s | %s |\n" "${names[$i]}" "${values[$i]}" + done + + echo "$line" +} + +# 函数:参数确认 +confirm_parameters() { + local params_str="$1" + display_parameters "$params_str" + + while true; do + read -p $'\n确认使用以上参数?(输入 o 继续,q 取消) ' -n 1 -r + echo + if [[ $REPLY =~ ^[Oo]$ ]]; then + echo "用户确认,继续操作..." + return 0 + elif [[ $REPLY =~ ^[Qq]$ ]]; then + echo "用户取消操作" + return 1 + else + echo "无效输入,请输入 o 或 q" + fi + done +} + +# 函数:生成自定义JRE +# 函数:生成自定义JRE +generate_jre() { + echo -e "\n==> 开始生成自定义JRE..." + local timestamp=$(date +"%Y-%m-%d %H:%M:%S") + echo "[$timestamp] 开始生成自定义JRE" >> "$ERROR_LOG_FILE" + + # 检查JRE目录是否已存在 + if [ -d "${JRE_DIR}" ]; then + echo -e "\033[0;33m警告:JRE目录已存在 - ${JRE_DIR}\033[0m" + while true; do + read -p "请选择操作 (1: 继续执行并删除现有目录, 2: 跳过生成JRE) [1/2]: " choice + case $choice in + 1) + echo "==> 删除现有JRE目录: ${JRE_DIR}" + rm -rf "${JRE_DIR}" || error_exit "无法删除现有JRE目录,请检查权限" + break + ;; + 2) + echo "==> 跳过JRE生成操作" + return 0 + ;; + *) + echo "无效输入,请输入1或2" + ;; + esac + done + fi + + # 检查JAR文件是否存在 + if [ ! -f "${MAIN_JAR}" ]; then + error_exit "JAR文件不存在 - ${MAIN_JAR}\n请检查文件是否被移动或删除" + fi + + # 分析依赖模块 + echo "==> 分析应用依赖的Java模块..." + MODULES=$(jdeps --print-module-deps --ignore-missing-deps "${MAIN_JAR}" 2>> "$ERROR_LOG_FILE" | tr -d '\n') + + if [ -z "${MODULES}" ]; then + echo "警告:未检测到依赖模块,使用默认模块集" + MODULES="java.base,java.desktop" + fi + echo "检测到的Java模块:${MODULES}" + echo "[$(date +"%Y-%m-%d %H:%M:%S")] 检测到的Java模块:${MODULES}" >> "$ERROR_LOG_FILE" + + # 生成JRE(修复输出路径错误,移除多余的) + if ! jlink \ + --module-path "${JDK_HOME}/jmods" \ + --add-modules "${MODULES}" \ + --output "${JRE_DIR}" \ + --strip-debug \ + --no-man-pages \ + --no-header-files; then + error_exit "JLink命令执行失败,详情请查看日志文件: $ERROR_LOG_FILE" + fi + + # 验证JRE + if [ ! -f "${JRE_DIR}/bin/java" ]; then + error_exit "JRE生成失败,未找到java可执行文件" + fi + + echo -e "\n==> JRE生成成功!" + echo "JRE版本信息:" + "${JRE_DIR}/bin/java" -version + echo "JRE路径:${JRE_DIR}" + echo "[$(date +"%Y-%m-%d %H:%M:%S")] JRE生成成功:${JRE_DIR}" >> "$ERROR_LOG_FILE" + return 0 +} + +# 函数:打包DMG +package_dmg() { + echo -e "\n==> 开始打包DMG文件..." + local timestamp=$(date +"%Y-%m-%d %H:%M:%S") + echo "[$timestamp] 开始打包DMG文件" >> "$ERROR_LOG_FILE" + + # 检查输出目录是否存在,不存在则创建 + if [ ! -d "${OUTPUT_DIR}" ]; then + echo "==> 输出目录不存在,创建目录: ${OUTPUT_DIR}" + mkdir -p "${OUTPUT_DIR}" || error_exit "无法创建输出目录: ${OUTPUT_DIR}" + else + echo "==> 输出目录已存在,无需创建: ${OUTPUT_DIR}" + fi + + # 检查JAR文件是否存在 + if [ ! -f "${MAIN_JAR}" ]; then + error_exit "JAR文件不存在 - ${MAIN_JAR}\n请检查文件是否被移动或删除" + fi + + # 检查JRE是否存在 + if [ ! -d "${JRE_DIR}" ] || [ ! -f "${JRE_DIR}/bin/java" ]; then + error_exit "未找到有效的JRE,请先执行生成JRE操作(选项1)" + fi + + + + # 执行打包 + if ! eval jpackage \ + --input . \ + --type dmg \ + --name "${APP_NAME}" \ + --app-version "${APP_VERSION}" \ + --main-jar "${MAIN_JAR}" \ + --main-class "${MAIN_CLASS}" \ + --runtime-image "${JRE_DIR}" \ + --dest "${OUTPUT_DIR}" \ +# --icon "${ICON_FILE}" \ + --vendor "小吴小吴bug全无" >> "$ERROR_LOG_FILE" 2>&1; then + error_exit "JPackage命令执行失败,详情请查看日志文件: $ERROR_LOG_FILE" + fi + + echo -e "\n==> DMG打包完成!" + echo "生成的DMG文件位于:${OUTPUT_DIR}" + echo "应用名称:${APP_NAME}-${APP_VERSION}.dmg" + echo "[$(date +"%Y-%m-%d %H:%M:%S")] DMG打包完成:${OUTPUT_DIR}/${APP_NAME}-${APP_VERSION}.dmg" >> "$ERROR_LOG_FILE" + return 0 +} + +# 函数:显示操作菜单 +show_menu() { + clear + echo "=====================================" + echo " 应用打包工具 " + echo "=====================================" + echo "1. 生成自定义JRE" + echo "2. 打包DMG文件(需先完成步骤1)" + echo "3. 退出" + echo "=====================================" +} + +# 初始化日志文件 +echo "=====================================" > "$ERROR_LOG_FILE" +echo "打包工具日志 - $(date +"%Y-%m-%d %H:%M:%S")" >> "$ERROR_LOG_FILE" +echo "=====================================" >> "$ERROR_LOG_FILE" + +# 主流程 +echo "==> 开始准备环境..." +echo "[$(date +"%Y-%m-%d %H:%M:%S")] 开始准备环境" >> "$ERROR_LOG_FILE" + +# 尝试获取主JAR并赋值给MAIN_JAR +echo "==> 正在检测JAR文件..." +if ! get_main_jar; then + error_exit "获取JAR文件失败" +fi +echo "==> 主JAR文件已设置为:$MAIN_JAR" +echo "[$(date +"%Y-%m-%d %H:%M:%S")] 主JAR文件已设置为:$MAIN_JAR" >> "$ERROR_LOG_FILE" + +# 初始化参数数组 +params_str=$(init_parameters) + +# 显示菜单并处理用户选择 +while true; do + show_menu + read -p "请选择操作 [1-3]: " choice + + case $choice in + 1) + # 生成自定义JRE + if confirm_parameters "$params_str"; then + # 仅确保基础输出目录存在,JRE目录在generate_jre中处理 + if [ ! -d "${OUTPUT_BASE}" ]; then + mkdir -p "${OUTPUT_BASE}" || error_exit "无法创建基础输出目录: ${OUTPUT_BASE}" + fi + if ! generate_jre; then + echo "生成JRE过程中出现错误,详情请查看日志" + fi + fi + read -p "按任意键返回菜单..." + ;; + 2) + # 打包DMG + if confirm_parameters "$params_str"; then + if ! package_dmg; then + echo "打包DMG过程中出现错误,详情请查看日志" + fi + fi + read -p "按任意键返回菜单..." + ;; + 3) + echo "==> 退出程序,再见!" + echo "[$(date +"%Y-%m-%d %H:%M:%S")] 正常退出程序" >> "$ERROR_LOG_FILE" + exit 0 + ;; + *) + echo "无效选择,请输入1-3之间的数字" + read -p "按任意键继续..." + ;; + esac +done \ No newline at end of file