l_ai_knowledge/scripts/start_all.sh

658 lines
18 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash
# 该脚本用于按需启动/停止Ollama和docker-compose服务
# 设置颜色
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m' # 无颜色
# 获取项目根目录(脚本所在目录的上一级)
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$( cd "$SCRIPT_DIR/.." && pwd )"
# 版本信息
VERSION="1.0.1" # 版本更新
SCRIPT_NAME=$(basename "$0")
# 显示帮助信息
show_help() {
echo -e "${GREEN}WeKnora 启动脚本 v${VERSION}${NC}"
echo -e "${GREEN}用法:${NC} $0 [选项]"
echo "选项:"
echo " -h, --help 显示帮助信息"
echo " -o, --ollama 启动Ollama服务"
echo " -d, --docker 启动Docker容器服务"
echo " -a, --all 启动所有服务(默认)"
echo " -s, --stop 停止所有服务"
echo " -c, --check 检查环境并诊断问题"
echo " -r, --restart 重新构建并重启指定容器"
echo " -l, --list 列出所有正在运行的容器"
echo " -v, --version 显示版本信息"
exit 0
}
# 显示版本信息
show_version() {
echo -e "${GREEN}WeKnora 启动脚本 v${VERSION}${NC}"
exit 0
}
# 日志函数
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
# 选择可用的 Docker Compose 命令(优先 docker compose其次 docker-compose
DOCKER_COMPOSE_BIN=""
DOCKER_COMPOSE_SUBCMD=""
detect_compose_cmd() {
# 优先使用 Docker Compose 插件
if docker compose version &> /dev/null; then
DOCKER_COMPOSE_BIN="docker"
DOCKER_COMPOSE_SUBCMD="compose"
return 0
fi
# 回退到 docker-compose (v1)
if command -v docker-compose &> /dev/null; then
if docker-compose version &> /dev/null; then
DOCKER_COMPOSE_BIN="docker-compose"
DOCKER_COMPOSE_SUBCMD=""
return 0
fi
fi
# 都不可用
return 1
}
# 检查并创建.env文件
check_env_file() {
log_info "检查环境变量配置..."
if [ ! -f "$PROJECT_ROOT/.env" ]; then
log_warning ".env 文件不存在,将从模板创建"
if [ -f "$PROJECT_ROOT/.env.example" ]; then
cp "$PROJECT_ROOT/.env.example" "$PROJECT_ROOT/.env"
log_success "已从 .env.example 创建 .env 文件"
else
log_error "未找到 .env.example 模板文件,无法创建 .env 文件"
return 1
fi
else
log_info ".env 文件已存在"
fi
# 检查必要的环境变量是否已设置
source "$PROJECT_ROOT/.env"
local missing_vars=()
# 检查基础变量
if [ -z "$DB_DRIVER" ]; then missing_vars+=("DB_DRIVER"); fi
if [ -z "$STORAGE_TYPE" ]; then missing_vars+=("STORAGE_TYPE"); fi
return 0
}
# 安装Ollama根据平台不同采用不同方法
install_ollama() {
# 检查是否为远程服务
get_ollama_base_url
if [ $IS_REMOTE -eq 1 ]; then
log_info "检测到远程Ollama服务配置无需在本地安装Ollama"
return 0
fi
log_info "本地Ollama未安装正在安装..."
OS=$(uname)
if [ "$OS" = "Darwin" ]; then
# Mac安装方式
log_info "检测到Mac系统使用brew安装Ollama..."
if ! command -v brew &> /dev/null; then
# 通过安装包安装
log_info "Homebrew未安装使用直接下载方式..."
curl -fsSL https://ollama.com/download/Ollama-darwin.zip -o ollama.zip
unzip ollama.zip
mv ollama /usr/local/bin
rm ollama.zip
else
brew install ollama
fi
else
# Linux安装方式
log_info "检测到Linux系统使用安装脚本..."
curl -fsSL https://ollama.com/install.sh | sh
fi
if [ $? -eq 0 ]; then
log_success "本地Ollama安装完成"
return 0
else
log_error "本地Ollama安装失败"
return 1
fi
}
# 获取Ollama基础URL检查是否为远程服务
get_ollama_base_url() {
check_env_file
# 从环境变量获取Ollama基础URL
OLLAMA_URL=${OLLAMA_BASE_URL:-"http://host.docker.internal:11434"}
# 提取主机部分
OLLAMA_HOST=$(echo "$OLLAMA_URL" | sed -E 's|^https?://||' | sed -E 's|:[0-9]+$||' | sed -E 's|/.*$||')
# 提取端口部分
OLLAMA_PORT=$(echo "$OLLAMA_URL" | grep -oE ':[0-9]+' | grep -oE '[0-9]+' || echo "11434")
# 检查是否为localhost或127.0.0.1
IS_REMOTE=0
if [ "$OLLAMA_HOST" = "localhost" ] || [ "$OLLAMA_HOST" = "127.0.0.1" ] || [ "$OLLAMA_HOST" = "host.docker.internal" ]; then
IS_REMOTE=0 # 本地服务
else
IS_REMOTE=1 # 远程服务
fi
}
# 启动Ollama服务
start_ollama() {
log_info "正在检查Ollama服务..."
# 提取主机和端口
get_ollama_base_url
log_info "Ollama服务地址: $OLLAMA_URL"
if [ $IS_REMOTE -eq 1 ]; then
log_info "检测到远程Ollama服务将直接使用远程服务不进行本地安装和启动"
# 检查远程服务是否可用
if curl -s "$OLLAMA_URL/api/tags" &> /dev/null; then
log_success "远程Ollama服务可访问"
return 0
else
log_warning "远程Ollama服务不可访问请确认服务地址正确且已启动"
return 1
fi
fi
# 以下为本地服务的处理
# 检查Ollama是否已安装
if ! command -v ollama &> /dev/null; then
install_ollama
if [ $? -ne 0 ]; then
return 1
fi
fi
# 检查Ollama服务是否已运行
if curl -s "http://localhost:$OLLAMA_PORT/api/tags" &> /dev/null; then
log_success "本地Ollama服务已经在运行端口$OLLAMA_PORT"
else
log_info "启动本地Ollama服务..."
# 注意:官方推荐使用 systemctl 或 launchctl 管理服务,直接后台运行仅用于临时场景
systemctl restart ollama || (ollama serve > /dev/null 2>&1 < /dev/null &)
# 等待服务启动
MAX_RETRIES=30
COUNT=0
while [ $COUNT -lt $MAX_RETRIES ]; do
if curl -s "http://localhost:$OLLAMA_PORT/api/tags" &> /dev/null; then
log_success "本地Ollama服务已成功启动端口$OLLAMA_PORT"
break
fi
echo -ne "等待Ollama服务启动... ($COUNT/$MAX_RETRIES)\r"
sleep 1
COUNT=$((COUNT + 1))
done
echo "" # 换行
if [ $COUNT -eq $MAX_RETRIES ]; then
log_error "本地Ollama服务启动失败"
return 1
fi
fi
log_success "本地Ollama服务地址: http://localhost:$OLLAMA_PORT"
return 0
}
# 停止Ollama服务
stop_ollama() {
log_info "正在停止Ollama服务..."
# 检查是否为远程服务
get_ollama_base_url
if [ $IS_REMOTE -eq 1 ]; then
log_info "检测到远程Ollama服务无需在本地停止"
return 0
fi
# 检查Ollama是否已安装
if ! command -v ollama &> /dev/null; then
log_info "本地Ollama未安装无需停止"
return 0
fi
# 查找并终止Ollama进程
if pgrep -x "ollama" > /dev/null; then
# 优先使用systemctl
if command -v systemctl &> /dev/null; then
sudo systemctl stop ollama
else
pkill -f "ollama serve"
fi
log_success "本地Ollama服务已停止"
else
log_info "本地Ollama服务未运行"
fi
return 0
}
# 检查Docker是否已安装
check_docker() {
log_info "检查Docker环境..."
if ! command -v docker &> /dev/null; then
log_error "未安装Docker请先安装Docker"
return 1
fi
# 检查并选择可用的 Docker Compose 命令
if detect_compose_cmd; then
if [ "$DOCKER_COMPOSE_BIN" = "docker" ]; then
log_info "已检测到 Docker Compose 插件 (docker compose)"
else
log_info "已检测到 docker-compose (v1)"
fi
else
log_error "未检测到 Docker Compose既没有 docker compose 也没有 docker-compose。请安装其中之一。"
return 1
fi
# 检查Docker服务运行状态
if ! docker info &> /dev/null; then
log_error "Docker服务未运行请启动Docker服务"
return 1
fi
log_success "Docker环境检查通过"
return 0
}
check_platform() {
# 检测当前系统平台
log_info "检测系统平台信息..."
if [ "$(uname -m)" = "x86_64" ]; then
export PLATFORM="linux/amd64"
elif [ "$(uname -m)" = "aarch64" ] || [ "$(uname -m)" = "arm64" ]; then
export PLATFORM="linux/arm64"
else
log_warning "未识别的平台类型:$(uname -m),将使用默认平台 linux/amd64"
export PLATFORM="linux/amd64"
fi
log_info "当前平台:$PLATFORM"
}
# 启动Docker容器
start_docker() {
log_info "正在启动Docker容器..."
# 检查Docker环境
check_docker
if [ $? -ne 0 ]; then
return 1
fi
# 检查.env文件
check_env_file
# 读取.env文件
source "$PROJECT_ROOT/.env"
storage_type=${STORAGE_TYPE:-local}
check_platform
# 进入项目根目录再执行docker-compose命令
cd "$PROJECT_ROOT"
# 启动基本服务
log_info "启动核心服务容器..."
# 统一通过已检测到的 Compose 命令启动
PLATFORM=$PLATFORM "$DOCKER_COMPOSE_BIN" $DOCKER_COMPOSE_SUBCMD up --build -d
if [ $? -ne 0 ]; then
log_error "Docker容器启动失败"
return 1
fi
log_success "所有Docker容器已成功启动"
# 显示容器状态
log_info "当前容器状态:"
"$DOCKER_COMPOSE_BIN" $DOCKER_COMPOSE_SUBCMD ps
return 0
}
# 停止Docker容器
stop_docker() {
log_info "正在停止Docker容器..."
# 检查Docker环境
check_docker
if [ $? -ne 0 ]; then
# 即使检查失败也尝试停止,以防万一
log_warning "Docker环境检查失败仍将尝试停止容器..."
fi
# 进入项目根目录再执行docker-compose命令
cd "$PROJECT_ROOT"
# 停止所有容器
"$DOCKER_COMPOSE_BIN" $DOCKER_COMPOSE_SUBCMD down --remove-orphans
if [ $? -ne 0 ]; then
log_error "Docker容器停止失败"
return 1
fi
log_success "所有Docker容器已停止"
return 0
}
# 列出所有正在运行的容器
list_containers() {
log_info "列出所有正在运行的容器..."
# 检查Docker环境
check_docker
if [ $? -ne 0 ]; then
return 1
fi
# 进入项目根目录再执行docker-compose命令
cd "$PROJECT_ROOT"
# 列出所有容器
echo -e "${BLUE}当前正在运行的容器:${NC}"
"$DOCKER_COMPOSE_BIN" $DOCKER_COMPOSE_SUBCMD ps --services | sort
return 0
}
# 重启指定容器
restart_container() {
local container_name="$1"
if [ -z "$container_name" ]; then
log_error "未指定容器名称"
echo "可用的容器有:"
list_containers
return 1
fi
log_info "正在重新构建并重启容器: $container_name"
# 检查Docker环境
check_docker
if [ $? -ne 0 ]; then
return 1
fi
check_platform
# 进入项目根目录再执行docker-compose命令
cd "$PROJECT_ROOT"
# 检查容器是否存在
if ! "$DOCKER_COMPOSE_BIN" $DOCKER_COMPOSE_SUBCMD ps --services | grep -q "^$container_name$"; then
log_error "容器 '$container_name' 不存在或未运行"
echo "可用的容器有:"
list_containers
return 1
fi
# 构建并重启容器
log_info "正在重新构建容器 '$container_name'..."
PLATFORM=$PLATFORM "$DOCKER_COMPOSE_BIN" $DOCKER_COMPOSE_SUBCMD build "$container_name"
if [ $? -ne 0 ]; then
log_error "容器 '$container_name' 构建失败"
return 1
fi
log_info "正在重启容器 '$container_name'..."
PLATFORM=$PLATFORM "$DOCKER_COMPOSE_BIN" $DOCKER_COMPOSE_SUBCMD up -d --no-deps "$container_name"
if [ $? -ne 0 ]; then
log_error "容器 '$container_name' 重启失败"
return 1
fi
log_success "容器 '$container_name' 已成功重新构建并重启"
return 0
}
# 检查系统环境
check_environment() {
log_info "开始环境检查..."
# 检查操作系统
OS=$(uname)
log_info "操作系统: $OS"
# 检查Docker
check_docker
# 检查.env文件
check_env_file
get_ollama_base_url
if [ $IS_REMOTE -eq 1 ]; then
log_info "检测到远程Ollama服务配置"
if curl -s "$OLLAMA_URL/api/tags" &> /dev/null; then
version=$(curl -s "$OLLAMA_URL/api/tags" | grep -o '"version":"[^"]*"' | cut -d'"' -f4)
log_success "远程Ollama服务可访问版本: $version"
else
log_warning "远程Ollama服务不可访问请确认服务地址正确且已启动"
fi
else
if command -v ollama &> /dev/null; then
log_success "本地Ollama已安装"
if curl -s "http://localhost:$OLLAMA_PORT/api/tags" &> /dev/null; then
version=$(curl -s "http://localhost:$OLLAMA_PORT/api/tags" | grep -o '"version":"[^"]*"' | cut -d'"' -f4)
log_success "本地Ollama服务正在运行版本: $version"
else
log_warning "本地Ollama已安装但服务未运行"
fi
else
log_warning "本地Ollama未安装"
fi
fi
# 检查磁盘空间
log_info "检查磁盘空间..."
df -h | grep -E "(Filesystem|/$)"
# 检查内存
log_info "检查内存使用情况..."
if [ "$OS" = "Darwin" ]; then
vm_stat | perl -ne '/page size of (\d+)/ and $size=$1; /Pages free: (\d+)/ and print "Free Memory: ", $1 * $size / 1048576, " MB\n"'
else
free -h | grep -E "(total|Mem:)"
fi
# 检查CPU
log_info "CPU信息:"
if [ "$OS" = "Darwin" ]; then
sysctl -n machdep.cpu.brand_string
echo "CPU核心数: $(sysctl -n hw.ncpu)"
else
grep "model name" /proc/cpuinfo | head -1
echo "CPU核心数: $(nproc)"
fi
# 检查容器状态
log_info "检查容器状态..."
if docker info &> /dev/null; then
docker ps -a
else
log_warning "无法获取容器状态Docker可能未运行"
fi
log_success "环境检查完成"
return 0
}
# 解析命令行参数
START_OLLAMA=false
START_DOCKER=false
STOP_SERVICES=false
CHECK_ENVIRONMENT=false
LIST_CONTAINERS=false
RESTART_CONTAINER=false
CONTAINER_NAME=""
# 没有参数时默认启动所有服务
if [ $# -eq 0 ]; then
START_OLLAMA=true
START_DOCKER=true
fi
while [ "$1" != "" ]; do
case $1 in
-h | --help ) show_help
;;
-o | --ollama ) START_OLLAMA=true
;;
-d | --docker ) START_DOCKER=true
;;
-a | --all ) START_OLLAMA=true
START_DOCKER=true
;;
-s | --stop ) STOP_SERVICES=true
;;
-c | --check ) CHECK_ENVIRONMENT=true
;;
-l | --list ) LIST_CONTAINERS=true
;;
-r | --restart ) RESTART_CONTAINER=true
CONTAINER_NAME="$2"
shift
;;
-v | --version ) show_version
;;
* ) log_error "未知选项: $1"
show_help
;;
esac
shift
done
# 执行环境检查
if [ "$CHECK_ENVIRONMENT" = true ]; then
check_environment
exit $?
fi
# 列出所有容器
if [ "$LIST_CONTAINERS" = true ]; then
list_containers
exit $?
fi
# 重启指定容器
if [ "$RESTART_CONTAINER" = true ]; then
restart_container "$CONTAINER_NAME"
exit $?
fi
# 执行服务操作
if [ "$STOP_SERVICES" = true ]; then
# 停止服务
stop_ollama
OLLAMA_RESULT=$?
stop_docker
DOCKER_RESULT=$?
# 显示总结
echo ""
log_info "=== 停止结果 ==="
if [ $OLLAMA_RESULT -eq 0 ]; then
log_success "✓ Ollama服务已停止"
else
log_error "✗ Ollama服务停止失败"
fi
if [ $DOCKER_RESULT -eq 0 ]; then
log_success "✓ Docker容器已停止"
else
log_error "✗ Docker容器停止失败"
fi
log_success "服务停止完成。"
else
# 启动服务
OLLAMA_RESULT=1
DOCKER_RESULT=1
if [ "$START_OLLAMA" = true ]; then
start_ollama
OLLAMA_RESULT=$?
fi
if [ "$START_DOCKER" = true ]; then
start_docker
DOCKER_RESULT=$?
fi
# 显示总结
echo ""
log_info "=== 启动结果 ==="
if [ "$START_OLLAMA" = true ]; then
if [ $OLLAMA_RESULT -eq 0 ]; then
log_success "✓ Ollama服务已启动"
else
log_error "✗ Ollama服务启动失败"
fi
fi
if [ "$START_DOCKER" = true ]; then
if [ $DOCKER_RESULT -eq 0 ]; then
log_success "✓ Docker容器已启动"
else
log_error "✗ Docker容器启动失败"
fi
fi
if [ "$START_OLLAMA" = true ] && [ "$START_DOCKER" = true ]; then
if [ $OLLAMA_RESULT -eq 0 ] && [ $DOCKER_RESULT -eq 0 ]; then
log_success "所有服务启动完成,可通过以下地址访问:"
echo -e "${GREEN} - 前端界面: http://localhost${NC}"
echo -e "${GREEN} - API接口: http://localhost:8080${NC}"
else
log_error "部分服务启动失败,请检查日志并修复问题"
fi
elif [ "$START_OLLAMA" = true ] && [ $OLLAMA_RESULT -eq 0 ]; then
log_success "Ollama服务启动完成可通过以下地址访问:"
echo -e "${GREEN} - Ollama API: http://localhost:$OLLAMA_PORT${NC}"
elif [ "$START_DOCKER" = true ] && [ $DOCKER_RESULT -eq 0 ]; then
log_success "Docker容器启动完成可通过以下地址访问:"
echo -e "${GREEN} - 前端界面: http://localhost${NC}"
echo -e "${GREEN} - API接口: http://localhost:8080${NC}"
fi
fi
exit 0