218 lines
6.1 KiB
Bash
218 lines
6.1 KiB
Bash
|
#!/bin/bash
|
|||
|
|
|||
|
# 函数:显示帮助信息
|
|||
|
show_help() {
|
|||
|
echo "股票基础分析应用管理脚本"
|
|||
|
echo ""
|
|||
|
echo "用法: $0 [命令] [参数]"
|
|||
|
echo ""
|
|||
|
echo "命令:"
|
|||
|
echo " list 列出所有运行的实例"
|
|||
|
echo " start [实例ID] 启动指定实例或所有实例"
|
|||
|
echo " stop [实例ID] 停止指定实例或所有实例"
|
|||
|
echo " restart [实例ID] 重启指定实例或所有实例"
|
|||
|
echo " logs [实例ID] 查看指定实例的日志"
|
|||
|
echo " status 显示实例状态概览"
|
|||
|
echo " remove [实例ID] 删除指定实例或所有实例"
|
|||
|
echo " rebuild [数量] 重新构建镜像并部署指定数量的实例"
|
|||
|
echo " update 热更新代码(不重建镜像,仅复制src目录)"
|
|||
|
echo ""
|
|||
|
echo "示例:"
|
|||
|
echo " $0 list 列出所有实例"
|
|||
|
echo " $0 start 2 启动实例2"
|
|||
|
echo " $0 stop all 停止所有实例"
|
|||
|
echo " $0 logs 1 查看实例1的日志"
|
|||
|
echo " $0 rebuild 2 重新构建并部署2个实例"
|
|||
|
echo " $0 update 热更新所有实例的代码"
|
|||
|
exit 1
|
|||
|
}
|
|||
|
|
|||
|
# 函数:列出所有实例
|
|||
|
list_instances() {
|
|||
|
echo "正在运行的实例:"
|
|||
|
docker ps --filter "name=stock-app-" --format "表格 {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
|||
|
}
|
|||
|
|
|||
|
# 函数:启动实例
|
|||
|
start_instance() {
|
|||
|
if [ "$1" = "all" ]; then
|
|||
|
echo "启动所有实例..."
|
|||
|
docker start $(docker ps -a --filter "name=stock-app-" -q)
|
|||
|
else
|
|||
|
echo "启动实例 $1..."
|
|||
|
docker start stock-app-$1
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
# 函数:停止实例
|
|||
|
stop_instance() {
|
|||
|
if [ "$1" = "all" ]; then
|
|||
|
echo "停止所有实例..."
|
|||
|
docker stop $(docker ps --filter "name=stock-app-" -q)
|
|||
|
else
|
|||
|
echo "停止实例 $1..."
|
|||
|
docker stop stock-app-$1
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
# 函数:重启实例
|
|||
|
restart_instance() {
|
|||
|
if [ "$1" = "all" ]; then
|
|||
|
echo "重启所有实例..."
|
|||
|
docker restart $(docker ps --filter "name=stock-app-" -q)
|
|||
|
else
|
|||
|
echo "重启实例 $1..."
|
|||
|
docker restart stock-app-$1
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
# 函数:查看实例日志
|
|||
|
view_logs() {
|
|||
|
echo "实例 $1 的日志:"
|
|||
|
docker logs stock-app-$1
|
|||
|
}
|
|||
|
|
|||
|
# 函数:显示状态概览
|
|||
|
show_status() {
|
|||
|
echo "实例状态概览:"
|
|||
|
echo "-----------------"
|
|||
|
echo "实例总数: $(docker ps -a --filter "name=stock-app-" --format "{{.Names}}" | wc -l)"
|
|||
|
echo "运行中: $(docker ps --filter "name=stock-app-" --format "{{.Names}}" | wc -l)"
|
|||
|
echo "已停止: $(docker ps -a --filter "name=stock-app-" --filter "status=exited" --format "{{.Names}}" | wc -l)"
|
|||
|
echo "-----------------"
|
|||
|
docker ps -a --filter "name=stock-app-" --format "表格 {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
|||
|
}
|
|||
|
|
|||
|
# 函数:删除实例
|
|||
|
remove_instance() {
|
|||
|
if [ "$1" = "all" ]; then
|
|||
|
echo "删除所有实例..."
|
|||
|
docker rm -f $(docker ps -a --filter "name=stock-app-" -q)
|
|||
|
else
|
|||
|
echo "删除实例 $1..."
|
|||
|
docker rm -f stock-app-$1
|
|||
|
fi
|
|||
|
}
|
|||
|
|
|||
|
# 函数:重新构建并部署
|
|||
|
rebuild_instances() {
|
|||
|
NUM_INSTANCES=$1
|
|||
|
|
|||
|
echo "开始全面重建流程..."
|
|||
|
|
|||
|
# 1. 停止所有实例
|
|||
|
echo "停止所有实例..."
|
|||
|
docker stop $(docker ps --filter "name=stock-app-" -q) 2>/dev/null
|
|||
|
|
|||
|
# 2. 删除所有实例
|
|||
|
echo "删除所有实例..."
|
|||
|
docker rm -f $(docker ps -a --filter "name=stock-app-" -q) 2>/dev/null
|
|||
|
|
|||
|
# 3. 重新构建镜像
|
|||
|
echo "重新构建镜像..."
|
|||
|
docker-compose build
|
|||
|
|
|||
|
# 4. 部署新实例
|
|||
|
echo "部署 $NUM_INSTANCES 个新实例..."
|
|||
|
./deploy-multiple.sh $NUM_INSTANCES
|
|||
|
|
|||
|
echo "重建完成!"
|
|||
|
}
|
|||
|
|
|||
|
# 函数:热更新代码
|
|||
|
update_code() {
|
|||
|
# 获取所有正在运行的实例
|
|||
|
RUNNING_INSTANCES=$(docker ps --filter "name=stock-app-" -q)
|
|||
|
|
|||
|
if [ -z "$RUNNING_INSTANCES" ]; then
|
|||
|
echo "没有发现正在运行的实例!"
|
|||
|
return 1
|
|||
|
fi
|
|||
|
|
|||
|
echo "发现 $(echo "$RUNNING_INSTANCES" | wc -l) 个实例需要更新..."
|
|||
|
|
|||
|
# 更新每个实例的代码
|
|||
|
for CONTAINER_ID in $RUNNING_INSTANCES; do
|
|||
|
CONTAINER_NAME=$(docker inspect --format='{{.Name}}' $CONTAINER_ID | sed 's/\///')
|
|||
|
echo "更新 $CONTAINER_NAME 的代码..."
|
|||
|
|
|||
|
# 复制 src 目录到容器
|
|||
|
docker cp ./src/. $CONTAINER_ID:/app/src/
|
|||
|
|
|||
|
# 重启 Flask 应用(如果使用的是gunicorn等进程管理器,需要向进程发送信号)
|
|||
|
echo "重启 $CONTAINER_NAME 中的应用..."
|
|||
|
docker exec $CONTAINER_ID sh -c "pkill -f 'python src/app.py' && nohup python src/app.py > /app/logs/app.log 2>&1 &"
|
|||
|
done
|
|||
|
|
|||
|
echo "所有实例代码已更新,并尝试重启应用!"
|
|||
|
echo "注意:如果应用启动方式不是 'python src/app.py',可能需要手动重启容器:"
|
|||
|
echo "./manage-instances.sh restart all"
|
|||
|
}
|
|||
|
|
|||
|
# 主逻辑
|
|||
|
if [ "$#" -lt 1 ]; then
|
|||
|
show_help
|
|||
|
fi
|
|||
|
|
|||
|
case "$1" in
|
|||
|
list)
|
|||
|
list_instances
|
|||
|
;;
|
|||
|
start)
|
|||
|
if [ "$#" -lt 2 ]; then
|
|||
|
echo "错误: 缺少实例ID参数"
|
|||
|
show_help
|
|||
|
fi
|
|||
|
start_instance $2
|
|||
|
;;
|
|||
|
stop)
|
|||
|
if [ "$#" -lt 2 ]; then
|
|||
|
echo "错误: 缺少实例ID参数"
|
|||
|
show_help
|
|||
|
fi
|
|||
|
stop_instance $2
|
|||
|
;;
|
|||
|
restart)
|
|||
|
if [ "$#" -lt 2 ]; then
|
|||
|
echo "错误: 缺少实例ID参数"
|
|||
|
show_help
|
|||
|
fi
|
|||
|
restart_instance $2
|
|||
|
;;
|
|||
|
logs)
|
|||
|
if [ "$#" -lt 2 ]; then
|
|||
|
echo "错误: 缺少实例ID参数"
|
|||
|
show_help
|
|||
|
fi
|
|||
|
view_logs $2
|
|||
|
;;
|
|||
|
status)
|
|||
|
show_status
|
|||
|
;;
|
|||
|
remove)
|
|||
|
if [ "$#" -lt 2 ]; then
|
|||
|
echo "错误: 缺少实例ID参数"
|
|||
|
show_help
|
|||
|
fi
|
|||
|
remove_instance $2
|
|||
|
;;
|
|||
|
rebuild)
|
|||
|
if [ "$#" -lt 2 ]; then
|
|||
|
echo "错误: 缺少实例数量参数"
|
|||
|
show_help
|
|||
|
fi
|
|||
|
rebuild_instances $2
|
|||
|
;;
|
|||
|
update)
|
|||
|
update_code
|
|||
|
;;
|
|||
|
help|--help|-h)
|
|||
|
show_help
|
|||
|
;;
|
|||
|
*)
|
|||
|
echo "错误: 未知命令 '$1'"
|
|||
|
show_help
|
|||
|
;;
|
|||
|
esac
|
|||
|
|
|||
|
exit 0
|