222 lines
6.6 KiB
Bash
222 lines
6.6 KiB
Bash
|
|
#!/bin/bash
|
|||
|
|
# 定义变量
|
|||
|
|
CONTAINER_NAME="elasticsearch"
|
|||
|
|
IMAGE_NAME="elasticsearch:7.17.28" # 镜像版本
|
|||
|
|
DATA_DIR="/docker-data/elasticsearch/data" # 数据目录
|
|||
|
|
CONFIG_DIR="/docker-data/elasticsearch/config" # 配置目录
|
|||
|
|
LOGS_DIR="/docker-data/elasticsearch/logs" # 日志目录
|
|||
|
|
HTTP_PORT=9200 # HTTP端口
|
|||
|
|
TRANSPORT_PORT=9300 # 内部通信端口
|
|||
|
|
CLUSTER_NAME="es-single-cluster" # 集群名称
|
|||
|
|
NODE_NAME="single-node" # 节点名称
|
|||
|
|
ES_JAVA_OPTS="-Xms1g -Xmx1g" # JVM内存(根据主机内存调整)
|
|||
|
|
|
|||
|
|
# 显示帮助信息
|
|||
|
|
show_help() {
|
|||
|
|
echo "使用方法: $0 [操作类型]"
|
|||
|
|
echo "操作类型:"
|
|||
|
|
echo " deploy - 部署并启动单机模式Elasticsearch"
|
|||
|
|
echo " remove - 停止并删除容器及数据目录"
|
|||
|
|
echo " logs - 查看容器日志"
|
|||
|
|
echo " status - 查看容器状态"
|
|||
|
|
echo " help - 显示帮助信息"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 准备环境(创建目录和配置文件)
|
|||
|
|
prepare_env() {
|
|||
|
|
# 创建数据、配置、日志目录并授权
|
|||
|
|
for dir in "$DATA_DIR" "$CONFIG_DIR" "$LOGS_DIR"; do
|
|||
|
|
if [ ! -d "$dir" ]; then
|
|||
|
|
echo "创建目录: $dir"
|
|||
|
|
mkdir -p "$dir"
|
|||
|
|
fi
|
|||
|
|
chown -R 1000:1000 "$dir" # 匹配容器内用户UID/GID
|
|||
|
|
chmod 755 "$dir"
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
# 生成单机模式配置文件(若不存在)
|
|||
|
|
if [ ! -f "$CONFIG_DIR/elasticsearch.yml" ]; then
|
|||
|
|
echo "生成单机模式配置文件: $CONFIG_DIR/elasticsearch.yml"
|
|||
|
|
cat > "$CONFIG_DIR/elasticsearch.yml" << EOF
|
|||
|
|
cluster.name: es-single-cluster
|
|||
|
|
node.name: single-node
|
|||
|
|
network.host: 0.0.0.0
|
|||
|
|
http.port: 9200
|
|||
|
|
transport.port: 9300
|
|||
|
|
discovery.type: single-node # 单机模式核心配置(必须保留)
|
|||
|
|
# 以下行必须删除或注释掉(与single-node冲突)
|
|||
|
|
# cluster.initial_master_nodes: ["single-node"]
|
|||
|
|
xpack.security.enabled: false
|
|||
|
|
http.cors.enabled: true
|
|||
|
|
http.cors.allow-origin: "*"
|
|||
|
|
bootstrap.memory_lock: true
|
|||
|
|
ingest.geoip.downloader.enabled: false
|
|||
|
|
EOF
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 配置JVM参数(若不存在)
|
|||
|
|
if [ ! -f "$CONFIG_DIR/jvm.options" ]; then
|
|||
|
|
echo "生成JVM配置文件: $CONFIG_DIR/jvm.options"
|
|||
|
|
# 修正后代码(拆分参数为两行)
|
|||
|
|
cat > "$CONFIG_DIR/jvm.options" << EOF
|
|||
|
|
-Xms1g
|
|||
|
|
-Xmx1g
|
|||
|
|
# 保留其他默认配置(如下)
|
|||
|
|
-XX:+UseG1GC
|
|||
|
|
-XX:MaxGCPauseMillis=50
|
|||
|
|
-XX:+HeapDumpOnOutOfMemoryError
|
|||
|
|
8-13:-XX:+UseConcMarkSweepGC
|
|||
|
|
8-13:-XX:CMSInitiatingOccupancyFraction=75
|
|||
|
|
8-13:-XX:+UseCMSInitiatingOccupancyOnly
|
|||
|
|
14-:-XX:+UseG1GC
|
|||
|
|
-XX:+HeapDumpOnOutOfMemoryError
|
|||
|
|
9-:-XX:+ExitOnOutOfMemoryError
|
|||
|
|
-XX:HeapDumpPath=data
|
|||
|
|
-XX:ErrorFile=logs/hs_err_pid%p.log
|
|||
|
|
8:-XX:+PrintGCDetails
|
|||
|
|
8:-XX:+PrintGCDateStamps
|
|||
|
|
8:-XX:+PrintTenuringDistribution
|
|||
|
|
8:-XX:+PrintGCApplicationStoppedTime
|
|||
|
|
8:-Xloggc:logs/gc.log
|
|||
|
|
8:-XX:+UseGCLogFileRotation
|
|||
|
|
8:-XX:NumberOfGCLogFiles=32
|
|||
|
|
8:-XX:GCLogFileSize=64m
|
|||
|
|
# JDK 9+ GC logging
|
|||
|
|
9-:-Xlog:gc*,gc+age=trace,safepoint:file=logs/gc.log:utctime,pid,tags:filecount=32,filesize=64m
|
|||
|
|
EOF
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 检查系统配置(解决vm.max_map_count问题)
|
|||
|
|
check_sys_config() {
|
|||
|
|
current_map_count=$(sysctl -n vm.max_map_count)
|
|||
|
|
if [ $current_map_count -lt 262144 ]; then
|
|||
|
|
echo "检测到vm.max_map_count值不足,需要调整..."
|
|||
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|||
|
|
echo "请使用sudo权限运行脚本,或手动执行:"
|
|||
|
|
echo "sudo sysctl -w vm.max_map_count=262144"
|
|||
|
|
echo "并在/etc/sysctl.conf中添加:vm.max_map_count=262144"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
# 临时调整
|
|||
|
|
sysctl -w vm.max_map_count=262144
|
|||
|
|
# 永久生效
|
|||
|
|
if ! grep -q "vm.max_map_count=262144" /etc/sysctl.conf; then
|
|||
|
|
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 部署启动
|
|||
|
|
deploy_es() {
|
|||
|
|
check_sys_config # 先检查系统配置
|
|||
|
|
prepare_env # 准备目录和配置
|
|||
|
|
|
|||
|
|
# 停止并删除现有容器
|
|||
|
|
if [ "$(docker ps -aq -f name=$CONTAINER_NAME)" ]; then
|
|||
|
|
echo "停止并删除现有容器: $CONTAINER_NAME"
|
|||
|
|
docker stop $CONTAINER_NAME
|
|||
|
|
docker rm $CONTAINER_NAME
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 启动单机模式容器
|
|||
|
|
echo "启动Elasticsearch单机模式..."
|
|||
|
|
docker run -d --privileged \
|
|||
|
|
--name $CONTAINER_NAME \
|
|||
|
|
--restart always \
|
|||
|
|
--ulimit nofile=65536:65536 \
|
|||
|
|
--ulimit nproc=4096:4096 \
|
|||
|
|
--ulimit memlock=-1:-1 \
|
|||
|
|
-p $HTTP_PORT:9200 \
|
|||
|
|
-p $TRANSPORT_PORT:9300 \
|
|||
|
|
-v $DATA_DIR:/usr/share/elasticsearch/data \
|
|||
|
|
-v $CONFIG_DIR/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
|
|||
|
|
-v $LOGS_DIR:/usr/share/elasticsearch/logs \
|
|||
|
|
-e TZ=Asia/Shanghai \
|
|||
|
|
$IMAGE_NAME
|
|||
|
|
|
|||
|
|
# 检查启动状态
|
|||
|
|
if [ "$(docker ps -aq -f name=$CONTAINER_NAME -f status=running)" ]; then
|
|||
|
|
echo "Elasticsearch单机模式启动成功!"
|
|||
|
|
echo "访问地址: http://localhost:$HTTP_PORT"
|
|||
|
|
echo "集群名称: $CLUSTER_NAME"
|
|||
|
|
echo "JVM配置: $ES_JAVA_OPTS"
|
|||
|
|
else
|
|||
|
|
echo "启动失败,请查看日志: ./$0 logs"
|
|||
|
|
docker logs $CONTAINER_NAME
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 移除容器和数据
|
|||
|
|
remove_es() {
|
|||
|
|
if [ "$(docker ps -aq -f name=$CONTAINER_NAME)" ]; then
|
|||
|
|
echo "停止容器: $CONTAINER_NAME"
|
|||
|
|
docker stop $CONTAINER_NAME
|
|||
|
|
echo "删除容器: $CONTAINER_NAME"
|
|||
|
|
docker rm $CONTAINER_NAME
|
|||
|
|
else
|
|||
|
|
echo "容器 $CONTAINER_NAME 不存在"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 询问是否删除数据目录
|
|||
|
|
for dir in "$DATA_DIR" "$CONFIG_DIR" "$LOGS_DIR"; do
|
|||
|
|
if [ -d "$dir" ]; then
|
|||
|
|
read -p "是否删除目录 $dir? (y/n) " confirm
|
|||
|
|
if [ "$confirm" = "y" ] || [ "$confirm" = "Y" ]; then
|
|||
|
|
echo "删除目录: $dir"
|
|||
|
|
rm -rf "$dir"
|
|||
|
|
else
|
|||
|
|
echo "保留目录: $dir"
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 查看日志
|
|||
|
|
show_logs() {
|
|||
|
|
if [ "$(docker ps -aq -f name=$CONTAINER_NAME)" ]; then
|
|||
|
|
echo "查看Elasticsearch日志(按Ctrl+C退出)..."
|
|||
|
|
docker logs -f $CONTAINER_NAME
|
|||
|
|
else
|
|||
|
|
echo "容器 $CONTAINER_NAME 不存在"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 查看状态
|
|||
|
|
show_status() {
|
|||
|
|
echo "容器状态:"
|
|||
|
|
docker ps -f name=$CONTAINER_NAME --format "表格:{{.Names}} {{.Status}} {{.Ports}}"
|
|||
|
|
if [ "$(docker ps -aq -f name=$CONTAINER_NAME -f status=running)" ]; then
|
|||
|
|
echo "服务健康检查:"
|
|||
|
|
curl -s "http://localhost:$HTTP_PORT/_cluster/health" | jq .
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# 主逻辑
|
|||
|
|
if [ $# -ne 1 ]; then
|
|||
|
|
show_help
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
case "$1" in
|
|||
|
|
deploy)
|
|||
|
|
deploy_es
|
|||
|
|
;;
|
|||
|
|
remove)
|
|||
|
|
remove_es
|
|||
|
|
;;
|
|||
|
|
logs)
|
|||
|
|
show_logs
|
|||
|
|
;;
|
|||
|
|
status)
|
|||
|
|
show_status
|
|||
|
|
;;
|
|||
|
|
help)
|
|||
|
|
show_help
|
|||
|
|
;;
|
|||
|
|
*)
|
|||
|
|
echo "无效操作: $1"
|
|||
|
|
show_help
|
|||
|
|
exit 1
|
|||
|
|
;;
|
|||
|
|
esac
|