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 |