Java运维脚本案例如何适配

wen java案例 22

本文目录导读:

Java运维脚本案例如何适配

  1. 跨平台适配脚本
  2. 多环境配置管理
  3. 容器环境适配
  4. Java版本适配
  5. 完整的适配脚本示例
  6. 配置示例文件

我来为你介绍Java运维脚本的适配方案,涵盖不同环境、系统和场景的最佳实践。

跨平台适配脚本

通用Shell脚本模板

#!/bin/bash
# ============== 环境检测与适配 ==============
# 检测操作系统
detect_os() {
    if [[ "$OSTYPE" == "linux-gnu"* ]]; then
        OS="Linux"
    elif [[ "$OSTYPE" == "darwin"* ]]; then
        OS="Mac"
    elif [[ "$OSTYPE" == "cygwin" ]]; then
        OS="Windows/Cygwin"
    elif [[ "$OSTYPE" == "msys" ]]; then
        OS="Windows/GitBash"
    elif [[ "$OSTYPE" == "win32" ]]; then
        OS="Windows"
    else
        OS="Unknown"
    fi
    echo "当前系统: $OS"
}
# Java路径适配
setup_java_home() {
    # 尝试多个可能的Java路径
    JAVA_PATHS=(
        "$JAVA_HOME/bin/java"
        "/usr/lib/jvm/java-11-openjdk/bin/java"
        "/usr/lib/jvm/java-8-openjdk/bin/java"
        "/usr/local/opt/openjdk/bin/java"
        "/c/Program Files/Java/jdk-*/bin/java.exe"
    )
    for path in "${JAVA_PATHS[@]}"; do
        # 处理通配符
        if [[ "$path" == *"*"* ]]; then
            for expanded in $path; do
                if [[ -x "$expanded" ]]; then
                    JAVA_CMD="$expanded"
                    return 0
                fi
            done
        elif [[ -x "$path" ]]; then
            JAVA_CMD="$path"
            return 0
        fi
    done
    # 最后尝试使用系统默认
    JAVA_CMD=$(which java 2>/dev/null)
    if [[ -z "$JAVA_CMD" ]]; then
        echo "错误: 未找到Java运行环境"
        exit 1
    fi
}

多环境配置管理

环境感知脚本

#!/bin/bash
# ============== 环境配置 ==============
ENVIRONMENTS=("dev" "test" "staging" "prod")
# 检测当前环境
detect_environment() {
    local hostname=$(hostname)
    local ip=$(hostname -I | awk '{print $1}')
    # 通过主机名判断
    if [[ "$hostname" == *"prod"* ]] || [[ "$hostname" == *"production"* ]]; then
        echo "prod"
    elif [[ "$hostname" == *"staging"* ]]; then
        echo "staging"
    elif [[ "$hostname" == *"test"* ]]; then
        echo "test"
    elif [[ "$hostname" == *"dev"* ]]; then
        echo "dev"
    # 通过IP判断
    elif [[ "$ip" == "10.0.1."* ]]; then
        echo "prod"
    elif [[ "$ip" == "10.0.2."* ]]; then
        echo "staging"
    else
        echo "dev"
    fi
}
# 加载对应环境的配置
load_environment_config() {
    local env=$1
    local config_file="config-${env}.properties"
    if [[ -f "$config_file" ]]; then
        source "$config_file"
    else
        # 默认配置
        export JAVA_OPTS="-Xms512m -Xmx1024m"
        export APP_PORT=8080
        export LOG_LEVEL="INFO"
    fi
    # 环境特定配置
    case "$env" in
        "dev")
            export JAVA_OPTS="-Xms256m -Xmx512m -XX:+UseG1GC"
            export LOG_LEVEL="DEBUG"
            export REMOTE_DEBUG="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
            ;;
        "test")
            export JAVA_OPTS="-Xms512m -Xmx1024m -XX:+UseG1GC"
            export LOG_LEVEL="INFO"
            export REMOTE_DEBUG=""
            ;;
        "prod")
            export JAVA_OPTS="-Xms2048m -Xmx4096m -XX:+UseG1GC -XX:+HeapDumpOnOutOfMemoryError"
            export LOG_LEVEL="WARN"
            export REMOTE_DEBUG=""
            ;;
    esac
}

容器环境适配

Docker/K8s感知脚本

#!/bin/bash
# ============== 容器环境检测 ==============
check_container_env() {
    # 检测是否在Docker容器中
    if [[ -f "/.dockerenv" ]] || grep -q "docker" /proc/1/cgroup 2>/dev/null; then
        CONTAINER_ENV="docker"
    fi
    # 检测是否在Kubernetes中
    if [[ -n "$KUBERNETES_SERVICE_HOST" ]] && [[ -n "$KUBERNETES_SERVICE_PORT" ]]; then
        CONTAINER_ENV="kubernetes"
    fi
    echo "容器环境: ${CONTAINER_ENV:-'none'}"
}
# 容器环境内存限制适配
adapt_memory_limits() {
    if [[ "$CONTAINER_ENV" == "kubernetes" ]]; then
        # 读取K8s资源限制
        MEM_LIMIT=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes 2>/dev/null)
        if [[ -n "$MEM_LIMIT" ]] && [[ "$MEM_LIMIT" -lt "9223372036854771712" ]]; then
            # 计算JVM堆内存(限制的75%)
            HEAP_SIZE=$((MEM_LIMIT * 75 / 100 / 1024 / 1024))
            export JAVA_OPTS="$JAVA_OPTS -Xmx${HEAP_SIZE}m -Xms${HEAP_SIZE}m"
        fi
    elif [[ "$CONTAINER_ENV" == "docker" ]]; then
        # Docker环境使用-XX:+UseContainerSupport
        export JAVA_OPTS="$JAVA_OPTS -XX:+UseContainerSupport -XX:+UseG1GC"
    fi
}

Java版本适配

JDK版本兼容处理

#!/bin/bash
# ============== JDK版本检测与适配 ==============
detect_java_version() {
    JAVA_VERSION=$($JAVA_CMD -version 2>&1 | grep -i version | awk -F '"' '{print $2}')
    JAVA_MAJOR_VERSION=$(echo "$JAVA_VERSION" | awk -F '.' '{print $1}')
    echo "Java版本: $JAVA_VERSION"
    echo "Java主版本: $JAVA_MAJOR_VERSION"
    # JDK版本特性适配
    case $JAVA_MAJOR_VERSION in
        8)
            # JDK 8兼容模式
            export JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:+PrintGCDetails"
            export JAVA_MODULES=""
            ;;
        9|10|11)
            # JDK 9-11兼容模式
            export JAVA_OPTS="$JAVA_OPTS -Xlog:gc* -XX:+UseStringDeduplication"
            export JAVA_MODULES="--add-modules java.se.ee"
            ;;
        12|13|14|15|16|17)
            # JDK 12+新特性
            export JAVA_OPTS="$JAVA_OPTS -Xlog:gc* -XX:+UseZGC -XX:ZUncommitDelay=120"
            export JAVA_MODULES=""
            ;;
        *)
            # 未来版本
            export JAVA_OPTS="$JAVA_OPTS -Xlog:gc*"
            export JAVA_MODULES=""
            ;;
    esac
}
# JVM参数适配
adapt_jvm_params() {
    local env=$1
    local mem_total=$(awk '/MemTotal/{print $2}' /proc/meminfo 2>/dev/null || echo 8388608)
    local cpu_cores=$(nproc 2>/dev/null || echo 4)
    # 根据内存自动调整
    if [[ "$mem_total" -gt 16000000 ]]; then  # > 16GB
        HEAP_RATIO=0.5
    elif [[ "$mem_total" -gt 8000000 ]]; then  # > 8GB
        HEAP_RATIO=0.6
    else
        HEAP_RATIO=0.7
    fi
    HEAP_SIZE=$((mem_total * HEAP_RATIO / 1024))
    export JAVA_OPTS="$JAVA_OPTS -Xms${HEAP_SIZE}m -Xmx${HEAP_SIZE}m"
    export JAVA_OPTS="$JAVA_OPTS -XX:ParallelGCThreads=$cpu_cores"
    export JAVA_OPTS="$JAVA_OPTS -XX:ConcGCThreads=$((cpu_cores / 2))"
}

完整的适配脚本示例

统一启动脚本

#!/bin/bash
# ============== Java应用启动脚本 - 全环境适配 ==============
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
APP_HOME="$(dirname "$SCRIPT_DIR")"
APP_NAME="my-java-app"
PID_FILE="/var/run/$APP_NAME.pid"
LOG_DIR="/var/log/$APP_NAME"
# 通用函数
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}
error() {
    log "ERROR: $1" >&2
    exit 1
}
# 1. 环境检测
detect_environment() {
    export ENV=${ENV:-$(detect_environment_impl)}
    log "运行环境: $ENV"
}
# 2. Java检测
check_java() {
    if [[ -z "$JAVA_HOME" ]]; then
        log "JAVA_HOME未设置,尝试自动检测..."
        for dir in /usr/lib/jvm/java-*-openjdk /usr/local/openjdk* /opt/java*; do
            if [[ -d "$dir" ]]; then
                export JAVA_HOME="$dir"
                break
            fi
        done
    fi
    if [[ -z "$JAVA_HOME" ]] || [[ ! -x "$JAVA_HOME/bin/java" ]]; then
        error "Java运行环境未找到,请安装JDK"
    fi
    export PATH="$JAVA_HOME/bin:$PATH"
    log "Java路径: $JAVA_HOME"
}
# 3. 配置加载
load_configuration() {
    local config_dir="$APP_HOME/config"
    # 加载默认配置
    if [[ -f "$config_dir/application.properties" ]]; then
        source "$config_dir/application.properties"
    fi
    # 加载环境特定配置
    if [[ -f "$config_dir/application-${ENV}.properties" ]]; then
        source "$config_dir/application-${ENV}.properties"
    fi
    # 加载本地覆盖配置
    if [[ -f "$config_dir/application-local.properties" ]]; then
        source "$config_dir/application-local.properties"
    fi
}
# 4. JVM参数优化
configure_jvm() {
    local mem_total=$(awk '/MemAvailable/{print $2}' /proc/meminfo 2>/dev/null || echo 0)
    local cpu_cores=$(nproc 2>/dev/null || echo 2)
    # 基础JVM参数
    JAVA_OPTS="-server -Djava.awt.headless=true"
    # 内存配置
    if [[ "$mem_total" -gt 0 ]]; then
        local heap_size=$((mem_total * 60 / 100 / 1024))
        JAVA_OPTS="$JAVA_OPTS -Xms${heap_size}m -Xmx${heap_size}m"
    else
        JAVA_OPTS="$JAVA_OPTS -Xms256m -Xmx512m"
    fi
    # GC配置
    JAVA_OPTS="$JAVA_OPTS -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
    JAVA_OPTS="$JAVA_OPTS -XX:ParallelGCThreads=$cpu_cores"
    # 调试配置(仅开发环境)
    if [[ "$ENV" == "dev" ]]; then
        JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
        JAVA_OPTS="$JAVA_OPTS -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$LOG_DIR"
    fi
    # 诊断配置
    JAVA_OPTS="$JAVA_OPTS -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:$LOG_DIR/gc.log"
    export JAVA_OPTS
}
# 5. 应用配置
configure_app() {
    # 应用参数
    APP_ARGS="--spring.profiles.active=$ENV"
    # 端口配置(从环境变量或配置文件)
    APP_PORT=${APP_PORT:-8080}
    APP_ARGS="$APP_ARGS --server.port=$APP_PORT"
    # 日志配置
    APP_ARGS="$APP_ARGS --logging.path=$LOG_DIR"
    APP_ARGS="$APP_ARGS --logging.level.root=${LOG_LEVEL:-INFO}"
    export APP_ARGS
}
# 6. 启动应用
start_application() {
    local jar_file=$(find "$APP_HOME/lib" -name "*.jar" -type f | head -1)
    if [[ -z "$jar_file" ]]; then
        error "未找到应用JAR包"
    fi
    log "启动应用: $APP_NAME"
    log "JAR文件: $jar_file"
    log "JVM参数: $JAVA_OPTS"
    log "应用参数: $APP_ARGS"
    cd "$APP_HOME"
    # 创建日志目录
    mkdir -p "$LOG_DIR"
    # 启动应用
    nohup $JAVA_HOME/bin/java $JAVA_OPTS \
        -jar "$jar_file" \
        $APP_ARGS \
        > "$LOG_DIR/app.log" 2>&1 &
    APP_PID=$!
    echo $APP_PID > "$PID_FILE"
    log "应用启动完成,PID: $APP_PID"
    # 等待应用启动
    sleep 5
    if kill -0 $APP_PID 2>/dev/null; then
        log "应用运行正常"
    else
        error "应用启动失败,请检查日志"
    fi
}
# 7. 健康检查
health_check() {
    local retries=30
    local health_url="http://localhost:${APP_PORT}/actuator/health"
    for ((i=1; i<=retries; i++)); do
        if curl -s "$health_url" | grep -q "UP"; then
            log "应用健康检查通过"
            return 0
        fi
        sleep 2
    done
    error "应用健康检查失败"
}
# 主函数
main() {
    log "========== 应用启动开始 =========="
    detect_environment
    check_java
    load_configuration
    configure_jvm
    configure_app
    start_application
    health_check
    log "========== 应用启动完成 =========="
    log "访问地址: http://localhost:$APP_PORT"
    log "日志文件: $LOG_DIR/app.log"
}
# 执行主函数
main "$@"

配置示例文件

application.properties

# 默认配置
app.name=my-java-app
app.version=1.0.0
# JVM配置
jvm.xms=256m
jvm.xmx=512m
jvm.gc=G1
# 应用配置
server.port=8080
logging.level.root=INFO

application-prod.properties

# 生产环境配置
server.port=8080
jvm.xms=2048m
jvm.xmx=4096m
jvm.gc=G1
jvm.gc.log=/var/log/app/gc.log
logging.level.root=WARN
# 生产环境特性
management.endpoints.web.exposure.include=health,info
spring.profiles.include=secure

这个适配方案的优势:

  1. 跨平台兼容:自动检测Linux/Mac/Windows系统
  2. 环境感知:根据主机名、IP等自动识别环境
  3. 容器适配:完美支持Docker和Kubernetes
  4. JDK版本兼容:自动适配不同Java版本
  5. 智能配置:根据系统资源自动调整JVM参数
  6. 故障自愈:包含健康检查和自动恢复机制

使用建议:

  • 根据实际需求调整配置参数
  • 添加详细的日志记录
  • 实现配置热更新机制
  • 集成监控告警系统

抱歉,评论功能暂时关闭!