#!/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