#!/usr/bin/env bash

# --------------------------------------------------
# OpenJDK 一键安装脚本(Rocky Linux 优化版)
# 版本:3.0
# 更新:2024-06-12
# 支持:Rocky Linux 9.x / RHEL 9.x
# --------------------------------------------------

# 启用严格模式(错误退出/未设变量检测/管道失败)
set -euo pipefail
shopt -s inherit_errexit
trap 'cleanup $?' EXIT

# -------------------- 全局配置 --------------------
WORK_DIR="/opt"                   # 工作目录
JAVA_VER="22.0.2"                 # Java版本号
JAVA_PATH="/usr/java"             # 安装路径
MIRROR_URL="https://mirrors.huaweicloud.com/openjdk/${JAVA_VER}/openjdk-${JAVA_VER}_linux-x64_bin.tar.gz"
LOG_FILE="/var/log/jdk_install_$(date +%Y%m%d%H%M%S).log" # 带时间戳的日志文件
MIN_SPACE=500                     # 最小所需磁盘空间(MB)

# -------------------- 初始化日志 --------------------
exec 3>&1 4>&2
exec > >(tee -a "${LOG_FILE}") 2>&1

# -------------------- 颜色输出函数 --------------------
print_color() {
  local color=$1
  local msg=$2
  local no_color='\033[0m'

  # 非交互式终端禁用颜色
  if [[ ! -t 1 ]]; then
    echo "${msg}"
    return
  fi

  case "${color}" in
    red)    echo -e "\033[31m${msg}${no_color}" ;;
    green)  echo -e "\033[32m${msg}${no_color}" ;;
    yellow) echo -e "\033[33m${msg}${no_color}" ;;
    blue)   echo -e "\033[34m${msg}${no_color}" ;;
    *)      echo -e "${msg}" ;;
  esac
}

# -------------------- 清理函数 --------------------
cleanup() {
  local exit_code=$1
  if [[ ${exit_code} -ne 0 ]]; then
    print_color "red" "\n[!] 安装失败!退出码:${exit_code}"
    print_color "yellow" "[+] 查看完整日志:tail -n 50 ${LOG_FILE}"
    [[ -f "${WORK_DIR}/.tmp_download" ]] && rm -f "${WORK_DIR}/.tmp_download"
  fi
}

# -------------------- 系统检查 --------------------
check_system() {
  print_color "blue" "[1/6] 系统环境检查..."

  # 发行版检测
  if ! grep -q 'Rocky Linux' /etc/redhat-release 2>/dev/null; then
    print_color "yellow" "[!] 非Rocky Linux系统,部分优化可能不生效"
  fi

  # 内核版本
  local kernel_ver
  kernel_ver=$(uname -r)
  print_color "blue" "|- 内核版本:${kernel_ver}"

  # 系统架构
  if [[ $(uname -m) != "x86_64" ]]; then
    print_color "red" "[!] 仅支持x86_64架构"
    exit 1
  fi
}

# -------------------- 依赖检查 --------------------
check_dependencies() {
  print_color "blue" "[2/6] 检查系统依赖..."

  local deps=("wget" "tar" "gzip")
  local missing=()

  for cmd in "${deps[@]}"; do
    if ! command -v "${cmd}" &>/dev/null; then
      missing+=("${cmd}")
    fi
  done

  if [[ ${#missing[@]} -gt 0 ]]; then
    print_color "yellow" "|- 缺少依赖:${missing[*]}"
    print_color "blue" "|- 正在安装依赖..."
  
    if ! dnf install -y "${missing[@]}" >> "${LOG_FILE}" 2>&1; then
      print_color "red" "[!] 依赖安装失败"
      exit 1
    fi
  fi
}

# -------------------- 环境预检 --------------------
precheck() {
  print_color "blue" "[3/6] 执行环境预检..."

  # 磁盘空间检查
  local free_space
  free_space=$(df -m "${WORK_DIR}" | awk 'NR==2 {print $4}')
  if [[ ${free_space} -lt ${MIN_SPACE} ]]; then
    print_color "red" "|- 磁盘空间不足!需要 ${MIN_SPACE}MB,可用 ${free_space}MB"
    exit 1
  fi

  # 目录可写性检查
  if ! touch "${WORK_DIR}/.write_test" 2>/dev/null; then
    print_color "red" "|- 目录不可写:${WORK_DIR}"
    exit 1
  fi
  rm -f "${WORK_DIR}/.write_test"

  # SELinux状态检查
  if [[ $(getenforce) == "Enforcing" ]]; then
    print_color "yellow" "|- SELinux处于强制模式,可能影响安装"
  fi
}

# -------------------- 下载模块 --------------------
download_jdk() {
  print_color "blue" "[4/6] 开始下载JDK..."
  local file_name="openjdk-${JAVA_VER}_linux-x64_bin.tar.gz"
  local tmp_file="${WORK_DIR}/.tmp_download"

  # 清理旧文件
  [[ -f "${WORK_DIR}/${file_name}" ]] && rm -f "${WORK_DIR}/${file_name}"

  # 使用临时文件下载(避免残留)
  if ! wget -c -q --progress=dot:giga "${MIRROR_URL}" -O "${tmp_file}"; then
    print_color "red" "|- 下载失败!请检查:"
    print_color "red" "   |- 网络连接:ping mirrors.huaweicloud.com"
    print_color "red" "   |- 手动测试:wget '${MIRROR_URL}'"
    exit 1
  fi

  # 重命名正式文件
  mv "${tmp_file}" "${WORK_DIR}/${file_name}"
  print_color "green" "|- 下载成功 → ${WORK_DIR}/${file_name}"
  print_color "blue" "|- 文件大小:$(du -sh ${WORK_DIR}/${file_name} | cut -f1)"
}

# -------------------- 安装模块 --------------------
install_jdk() {
  print_color "blue" "[5/6] 安装JDK ${JAVA_VER}..."
  local file_name="openjdk-${JAVA_VER}_linux-x64_bin.tar.gz"
  local jdk_dir="jdk-${JAVA_VER}"

  # 清理旧安装
  [[ -d "${JAVA_PATH}" ]] && rm -rf "${JAVA_PATH}"
  mkdir -p "${JAVA_PATH}"

  # 解压文件
  if ! tar -xzf "${WORK_DIR}/${file_name}" -C "${JAVA_PATH}"; then
    print_color "red" "|- 解压失败!可能文件损坏"
    print_color "yellow" "|- 建议手动验证:tar -tzf ${WORK_DIR}/${file_name}"
    exit 1
  fi

  # 权限修复
  chown -R root:root "${JAVA_PATH}"
  chmod -R 755 "${JAVA_PATH}"
}

# -------------------- 配置模块 --------------------
configure_env() {
  print_color "blue" "[6/6] 配置环境变量..."
  local profile_file="/etc/profile.d/jdk.sh"
  local jdk_path="${JAVA_PATH}/jdk-${JAVA_VER}"

  # 生成配置文件
  cat > "${profile_file}" << EOF
# OpenJDK Environment
export JAVA_HOME="${jdk_path}"
export PATH="\$JAVA_HOME/bin:\$PATH"
export CLASSPATH=".:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib/tools.jar"
EOF

  # 立即生效
  source "${profile_file}"

  # 验证配置
  if ! java -version >> "${LOG_FILE}" 2>&1; then
    print_color "red" "|- 环境配置失败!"
    print_color "yellow" "|- 手动验证命令:source ${profile_file} && java -version"
    exit 1
  fi
}

# -------------------- 主函数 --------------------
main() {
  clear
  print_color "green" "开始 OpenJDK ${JAVA_VER} 安装流程"
  
  check_system
  check_dependencies
  precheck
  download_jdk
  install_jdk
  configure_env

  # 最终验证
  local installed_ver
  installed_ver=$(java -version 2>&1 | awk -F '"' '/version/ {print $2}')
  print_color "green" "\n✅ 安装成功!Java版本:${installed_ver}"
}

# -------------------- 执行入口 --------------------
main
exit 0

最后修改:2025 年 02 月 21 日
如果觉得我的文章对你有用,请随意赞赏