本文目录导读:

我来为你介绍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
这个适配方案的优势:
- 跨平台兼容:自动检测Linux/Mac/Windows系统
- 环境感知:根据主机名、IP等自动识别环境
- 容器适配:完美支持Docker和Kubernetes
- JDK版本兼容:自动适配不同Java版本
- 智能配置:根据系统资源自动调整JVM参数
- 故障自愈:包含健康检查和自动恢复机制
使用建议:
- 根据实际需求调整配置参数
- 添加详细的日志记录
- 实现配置热更新机制
- 集成监控告警系统