使用sh脚处理docker容器jar文件替换
1、拷贝docker容器中的jar到宿主机并提取配置文件。
extract_jar.sh脚本
#!/bin/bash
# ==== 配置文件路径 ====
CONTAINER_CONF="./containers.conf"
PATHS_CONF="/root/script/extract_paths.conf"
LOG_FILE="./extraction_log.txt"
# ==== 函数:日志记录 ====
log_message() {
echo "$1" | tee -a "$LOG_FILE"
}
# ==== 校验配置文件 ====
if [[ ! -f "$CONTAINER_CONF" ]]; then
log_message "❌ 缺少容器配置文件: $CONTAINER_CONF"
exit 1
fi
if [[ ! -f "$PATHS_CONF" ]]; then
log_message "❌ 缺少路径配置文件: $PATHS_CONF"
exit 1
fi
# ==== 初始化日志 ====
log_message "日志开始:$(date)"
log_message "==== 开始提取配置文件 ===="
# ==== 创建输出目录 ====
timestamp=$(date +"%Y%m%d_%H%M%S")
BASE_OUTPUT_DIR="jar_configs_${timestamp}"
mkdir -p "$BASE_OUTPUT_DIR"
# ==== 读取容器配置 ====
while while IFS= read -r line || [[ -n "$line" ]]; do
[[ -z "$line" || "$line" =~ ^# ]] && continue
# 使用 IFS 来拆分行,避免多字符分隔符
IFS=":" read -r container jar_path <<< "$line"
# 校验容器名和路径
if [[ -z "$container" || -z "$jar_path" ]]; then
log_message "❌ 错误:容器名或路径为空,跳过该行。"
continue
fi
container_dir="$BASE_OUTPUT_DIR/$container"
mkdir -p "$container_dir"
# 去除前后空格
jar_path=$(echo "$jar_path" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# ==== 拷贝 JAR 文件 ====
log_message "准备执行 docker cp $container:$jar_path $container_dir"
if ! docker cp "$container:$jar_path" "$container_dir"; then
log_message "❌ 错误:无法从容器 $container 拷贝文件 $jar_path"
continue
fi
# ==== 解压指定文件 ====
log_message "解压指定文件..."
(
cd "$container_dir" || exit
# 获取 JAR 文件内容列表
jar tf "app.jar" > jar_content_list.txt
# 直接从 PATHS_CONF 中提取路径并解压
grep -vE '^#|^$' "$PATHS_CONF" | while IFS= read -r file_to_extract || [[ -n "$line" ]]; do
# 检查文件是否存在于 JAR 文件中
file_to_extract=$(echo "$file_to_extract" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
if grep -Fxq "$file_to_extract" jar_content_list.txt; then
log_message " ✅ 解压: $file_to_extract"
if ! jar xf "app.jar" "$file_to_extract" >> "$LOG_FILE" 2>&1; then
log_message "❌ 解压失败: $file_to_extract"
fi
else
log_message " ⚠️ 未找到: $file_to_extract"
fi
done
)
log_message "✅ 完成容器: $container"
done < "$CONTAINER_CONF"
log_message ""
log_message "🎉 所有提取完成,结果保存在: $BASE_OUTPUT_DIR"
log_message "日志已记录在: $LOG_FILE"
2、containers.conf(容器ID和文件路径)、extract_paths.conf(文件中的路径)配置文件
2.1、containers.conf配置文件
# 容器名::容器内JAR路径
02f342cea777:/tmp/app.jar
2.2、extract_paths.conf配置文件
BOOT-INF/classes/application.yml
BOOT-INF/classes/application-dev.yml
BOOT-INF/classes/application-prod.yml
3、重新打包jar文件并拷贝之容器内,重新启动容器
repack_jar.sh脚本
#!/bin/bash
# ==== 配置文件路径 ====
CONTAINER_CONF="./containers.conf" # 容器配置文件
LOG_FILE="./repack_log.txt" # 打包日志文件
BASE_OUTPUT_DIR="./jar_configs" # 默认输出目录,来自 `extract_jar.sh`
# 检查是否提供了命令行参数作为BASE_OUTPUT_DIR
if [[ $# -ge 1 ]]; then
BASE_OUTPUT_DIR="$1"
log_message "ℹ️ 使用命令行指定的输出目录: $BASE_OUTPUT_DIR"
fi
# ==== 函数:日志记录 ====
log_message() {
echo "$1" | tee -a "$LOG_FILE"
}
# ==== 校验配置文件 ====
if [[ ! -f "$CONTAINER_CONF" ]]; then
log_message "❌ 缺少容器配置文件: $CONTAINER_CONF"
exit 1
fi
# 检查解压目录是否存在
if [[ ! -d "$BASE_OUTPUT_DIR" ]]; then
log_message "❌ 缺少解压后的输出目录: $BASE_OUTPUT_DIR"
exit 1
fi
# ==== 初始化日志 ====
log_message "日志开始:$(date)"
log_message "==== 开始重新打包 JAR 文件 ===="
log_message "使用的输出目录: $BASE_OUTPUT_DIR"
# ==== 读取容器配置 ====
while IFS= read -r line || [[ -n "$line" ]]; do
[[ -z "$line" || "$line" =~ ^# ]] && continue
# 使用 IFS 来拆分行,避免多字符分隔符
IFS=":" read -r container jar_path <<< "$line"
# 校验容器名和路径
if [[ -z "$container" || -z "$jar_path" ]]; then
log_message "❌ 错误:容器名或路径为空,跳过该行。"
continue
fi
container_dir="${BASE_OUTPUT_DIR}/${container}"
if [[ ! -d "$container_dir" ]]; then
log_message "❌ 错误:容器文件夹 $container_dir 不存在,跳过该容器。"
continue
fi
# ==== 重新打包 JAR 文件 ====
log_message "正在重新打包 JAR 文件($container)..."
(
cd "$container_dir" || exit
jar uf "app.jar" BOOT-INF/classes/* # 假设修改后的配置文件都在 `BOOT-INF/classes/` 下
# 检查是否打包成功
if [ $? -eq 0 ]; then
log_message "✅ JAR 文件重新打包成功($container)"
else
log_message "❌ JAR 文件重新打包失败($container)"
exit 1
fi
)
jar_path=$(echo "$jar_path" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
# ==== 拷贝 JAR 文件到容器 ====
log_message "正在拷贝 JAR 文件到容器($container)..."
if ! docker cp "$container_dir/app.jar" "$container:$jar_path"; then
log_message "❌ 无法拷贝 JAR 文件到容器 $container"
continue
fi
# ==== 重启容器 ====
log_message "正在重启容器 $container..."
if ! docker restart "$container"; then
log_message "❌ 容器 $container 重启失败"
continue
fi
log_message "✅ 完成容器: $container"
done < "$CONTAINER_CONF"
log_message ""
log_message "🎉 所有打包完成,结果已拷贝到容器并重启!"
log_message "日志已记录在: $LOG_FILE"
可以指定路径执行:repack_jar.sh ./jar_configs