Files
2026-07-13 12:35:20 +08:00

128 lines
4.3 KiB
Bash

#!/bin/bash
set -euo pipefail
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"
}
log "Xiaozhi Client Docker 容器启动中..."
# 检查工作目录初始化状态
log "检查工作目录初始化状态..."
# 检查关键配置文件是否存在
if [ ! -f "/workspaces/xiaozhi.config.json" ] || [ ! -f "/workspaces/package.json" ]; then
log "初始化工作目录..."
log "将模板文件复制到 ~/xiaozhi-client (挂载到 /workspaces)"
# 确保目录存在
mkdir -p /workspaces
# 复制模板文件到工作目录
if ! cp -r /templates-backup/* /workspaces/; then
log "错误: 复制模板文件失败"
exit 1
fi
log "工作目录初始化完成"
log "配置文件位置: ~/xiaozhi-client/xiaozhi.config.json"
else
log "工作目录已存在配置文件,跳过初始化"
fi
# 确保 Node.js 依赖已安装
cd /workspaces
if [ ! -d "node_modules" ]; then
log "安装 Node.js 项目依赖..."
if ! npm install; then
log "错误: Node.js 依赖安装失败"
exit 1
fi
log "Node.js 依赖安装完成"
else
log "Node.js 依赖已存在,跳过安装"
fi
# 动态安装 Python 依赖
log "检查 Python 依赖..."
install_python_dependencies() {
local requirements_file="$1"
local requirements_name="$2"
if [ -f "$requirements_file" ]; then
# 检查文件是否有非注释、非空行的内容
if grep -v '^#' "$requirements_file" | grep -v '^$' | head -1 > /dev/null 2>&1; then
log "发现 $requirements_name 文件,开始安装 Python 依赖..."
# 确保使用虚拟环境
export PATH="/opt/venv/bin:$PATH"
# 显示将要安装的包(仅非注释行)
log "将要安装的包:"
grep -v '^#' "$requirements_file" | grep -v '^$' | while read -r line; do
log " - $line"
done
# 安装依赖
if pip install -r "$requirements_file"; then
log "✓ Python 依赖安装成功"
# 记录安装的包版本(用于调试)
log "已安装的 Python 包版本:"
pip list | grep -E "(mcp|fastmcp|httpx|websockets|pydantic)" | while read -r line; do
log " $line"
done
else
log "⚠️ 警告: Python 依赖安装失败,但容器将继续启动"
log "请检查 $requirements_name 文件中的包名和版本是否正确"
return 1
fi
else
log "$requirements_name 文件存在但为空或只包含注释,跳过安装"
fi
else
log "$requirements_name 文件不存在,跳过 Python 依赖安装"
fi
}
# 安装用户自定义的 Python 依赖(优先级更高)
install_python_dependencies "/workspaces/requirements.txt" "用户自定义 requirements.txt"
# 如果用户没有自定义 requirements.txt,则检查是否需要安装默认依赖
if [ ! -f "/workspaces/requirements.txt" ]; then
log "未找到用户自定义 requirements.txt,检查是否需要安装默认 Python 依赖..."
# 检查是否已经安装了基本的 MCP 包
export PATH="/opt/venv/bin:$PATH"
if ! python -c "import mcp" 2>/dev/null; then
log "检测到 MCP 包未安装,将从模板安装默认依赖..."
if [ -f "/templates-backup/requirements.txt" ]; then
install_python_dependencies "/templates-backup/requirements.txt" "默认模板 requirements.txt"
fi
else
log "MCP 包已安装,跳过默认依赖安装"
fi
fi
# 清理可能存在的旧 PID 文件(容器重启时)
log "清理容器启动前的状态..."
if [ -f "/workspaces/.xiaozhi-client.pid" ]; then
log "发现旧的 PID 文件,正在清理..."
rm -f "/workspaces/.xiaozhi-client.pid"
log "旧 PID 文件已清理"
fi
# 清理其他可能的 PID 文件
find /workspaces -name "*.pid" -type f -delete 2>/dev/null || true
log "启动 xiaozhi-client..."
# 如果没有提供参数或者第一个参数是选项,则使用默认命令
if [ $# -eq 0 ] || [[ "$1" == -* ]]; then
# 没有参数或第一个参数是选项,使用默认的xiaozhi命令
exec xiaozhi "$@"
else
# 有参数且第一个参数不是选项,直接执行
exec "$@"
fi