使用sh脚处理docker容器jar文件替换

  |   0 评论   |   0 浏览

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


标题:使用sh脚处理docker容器jar文件替换
作者:zytops
地址:https://zytops.com/articles/2025/08/09/1754710236643.html