2 Commits

Author SHA1 Message Date
macbookpro
e377b49244 Merge remote-tracking branch 'origin/master' 2025-07-31 21:19:11 +08:00
macbookpro
8516f8c854 【fix】添加打包命令 2025-07-31 21:18:38 +08:00

View File

@@ -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