This commit is contained in:
Your Name
2026-07-17 09:24:47 +08:00
commit 530e7f839d
4353 changed files with 731879 additions and 0 deletions
+361
View File
@@ -0,0 +1,361 @@
#!/usr/bin/env bash
# 抖音客服系统 - Linux 一键安装(兼容宝塔 Python 项目 + 原生 CentOS/Ubuntu
# 用法:
# ./install.sh # 自动探测可用 Python 并安装
# ./install.sh --diagnose # 仅列出本机 Python 探测结果
# AUTO_BUILD_PYTHON=1 ./install.sh # 无可用 Python 时自动编译 3.11
# KEFU_PYTHON=/path/to/python3 ./install.sh # 手动指定
set -euo pipefail
ROOT="$(cd "$(dirname "$0")" && pwd)"
cd "$ROOT"
MIN_PY_MAJOR=3
MIN_PY_MINOR=10
DIAGNOSE=0
AUTO_BUILD="${AUTO_BUILD_PYTHON:-0}"
for arg in "$@"; do
case "$arg" in
--diagnose) DIAGNOSE=1 ;;
--build-python) AUTO_BUILD=1 ;;
esac
done
echo "========================================"
echo " 抖音客服系统 - 依赖安装"
echo "========================================"
echo
# ---------- Python 检测工具 ----------
check_python_ssl() {
"$1" -c "import ssl" 2>/dev/null
}
check_python_version() {
"$1" -c "import sys; sys.exit(0 if sys.version_info >= ($MIN_PY_MAJOR, $MIN_PY_MINOR) else 1)" 2>/dev/null
}
python_brief() {
local py="$1"
if [ ! -x "$py" ]; then
echo "不存在"
return
fi
local ver ssl
ver="$("$py" -V 2>&1 | awk '{print $2}')" || ver="?"
if check_python_ssl "$py"; then
ssl="$("$py" -c "import ssl; print(ssl.OPENSSL_VERSION)" 2>/dev/null)"
else
ssl="无SSL"
fi
echo "${ver} | ${ssl}"
}
try_python() {
local py="$1"
[ -n "$py" ] && [ -x "$py" ] || return 1
check_python_ssl "$py" || return 1
check_python_version "$py" || return 1
return 0
}
# 收集候选 Python(去重,高版本优先)
declare -a CANDIDATES=()
declare -A SEEN=()
add_candidate() {
local py="$1"
[ -n "$py" ] || return 0
if [ -x "$py" ] && [ -z "${SEEN[$py]:-}" ]; then
SEEN[$py]=1
CANDIDATES+=("$py")
fi
}
collect_python_candidates() {
CANDIDATES=()
SEEN=()
# 1) 用户指定
[ -n "${KEFU_PYTHON:-}" ] && add_candidate "$KEFU_PYTHON"
# 2) 当前 shell(宝塔 source 项目环境后 which python 会指向项目 Python
add_candidate "$(command -v python 2>/dev/null || true)"
add_candidate "$(command -v python3 2>/dev/null || true)"
add_candidate "$(command -v python3.11 2>/dev/null || true)"
add_candidate "$(command -v python3.10 2>/dev/null || true)"
# 3) 虚拟环境
[ -n "${VIRTUAL_ENV:-}" ] && add_candidate "${VIRTUAL_ENV}/bin/python"
# 4) 宝塔 Python 项目环境(多版本目录名,动态扫描,不写死单一版本)
local base py ver_dir
for base in \
/www/server/pyporject_evn/versions \
/home/www/server/pyporject_evn/versions \
/www/server/panel/pyenv/versions \
/www/server/python_project/versions; do
[ -d "$base" ] || continue
for ver_dir in "$base"/*; do
[ -d "$ver_dir" ] || continue
for py in "$ver_dir"/bin/python3.* "$ver_dir"/bin/python3 "$ver_dir"/bin/python; do
add_candidate "$py"
done
done
done
# 5) 源码/包管理器安装路径
for py in \
/usr/local/python3.11/bin/python3.11 \
/usr/local/python3.10/bin/python3.10 \
/usr/local/bin/python3.11 /usr/local/bin/python3.10 \
/usr/bin/python3.11 /usr/bin/python3.10; do
add_candidate "$py"
done
# 6) conda
add_candidate "${CONDA_PREFIX:-}/bin/python"
for py in /opt/miniconda3/envs/*/bin/python /root/miniconda3/envs/*/bin/python; do
[ -e "$py" ] && add_candidate "$py"
done
}
sort_candidates_by_version() {
local -a sorted=()
local py ver
while IFS= read -r line; do
sorted+=("$line")
done < <(
for py in "${CANDIDATES[@]}"; do
ver="$("$py" -V 2>&1 | awk '{print $2}' || echo 0.0.0)"
echo "$ver $py"
done | sort -t. -k1,1nr -k2,2nr -k3,3nr | awk '{print $2}'
)
CANDIDATES=("${sorted[@]}")
}
select_python() {
local py
collect_python_candidates
if [ "${#CANDIDATES[@]}" -eq 0 ]; then
return 1
fi
sort_candidates_by_version
for py in "${CANDIDATES[@]}"; do
if try_python "$py"; then
echo "$py"
return 0
fi
done
return 1
}
print_diagnose() {
local py tag
echo "[诊断] 本机 Python 探测结果(需要 3.10+ 且带 SSL:"
echo
collect_python_candidates
if [ "${#CANDIDATES[@]}" -eq 0 ]; then
echo " (未找到任何 Python 可执行文件)"
return
fi
sort_candidates_by_version
for py in "${CANDIDATES[@]}"; do
if try_python "$py"; then tag="可用"; else tag="不可用"; fi
printf " [%s] %s\n %s\n" "$tag" "$py" "$(python_brief "$py")"
done
echo
if [ -d /www/server/panel ] || [ -d /www/server/pyporject_evn ] || [ -d /home/www/server/pyporject_evn ]; then
echo " 环境: 检测到宝塔面板"
echo " 提示: 宝塔 Python 项目需先 source 项目环境,或确保 pyporject_evn 下 Python 带 _ssl"
else
echo " 环境: 原生 Linux"
fi
}
build_python311() {
local PYVER="3.11.9" PY_SHORT="3.11"
local PREFIX="/usr/local/python${PY_SHORT}"
local PY_BIN="${PREFIX}/bin/python${PY_SHORT}"
local SRC="/usr/src/Python-${PYVER}"
if [ "$(id -u)" -ne 0 ]; then
echo "[错误] 自动编译 Python 需要 root 权限"
return 1
fi
if [ -x "$PY_BIN" ] && try_python "$PY_BIN"; then
echo "[OK] 已存在可用 Python: $PY_BIN"
echo "$PY_BIN"
return 0
fi
echo "[编译] 未找到可用 Python,开始编译 ${PYVER} -> ${PREFIX}(约 10 分钟)"
if command -v yum &>/dev/null; then
yum groupinstall -y "Development Tools" 2>/dev/null || yum install -y gcc make
yum install -y openssl openssl-devel libffi-devel zlib-devel bzip2-devel \
readline-devel sqlite-devel xz-devel wget tar
elif command -v apt-get &>/dev/null; then
apt-get update
apt-get install -y build-essential libssl-dev zlib1g-dev libbz2-dev \
libreadline-dev libsqlite3-dev libffi-dev wget tar
else
echo "[错误] 不支持的包管理器"
return 1
fi
mkdir -p /usr/src && cd /usr/src
if [ ! -f "Python-${PYVER}.tgz" ]; then
wget -q "https://www.python.org/ftp/python/${PYVER}/Python-${PYVER}.tgz" \
|| wget -q "https://registry.npmmirror.com/-/binary/python/${PYVER}/Python-${PYVER}.tgz"
fi
rm -rf "$SRC" && tar xzf "Python-${PYVER}.tgz" && cd "$SRC"
./configure --prefix="$PREFIX" --enable-optimizations --with-openssl=/usr
make -j"$(nproc 2>/dev/null || echo 2)"
make altinstall
try_python "$PY_BIN" || return 1
echo "[OK] 编译完成: $PY_BIN"
echo "$PY_BIN"
}
# ---------- 选择 Python ----------
if [ "$DIAGNOSE" -eq 1 ]; then
print_diagnose
exit 0
fi
PYTHON=""
if [ -n "${KEFU_PYTHON:-}" ]; then
if [ ! -x "$KEFU_PYTHON" ]; then
echo "[错误] KEFU_PYTHON 不存在: $KEFU_PYTHON"
echo " 运行 ./install.sh --diagnose 查看本机可用 Python"
exit 1
fi
if ! try_python "$KEFU_PYTHON"; then
echo "[错误] KEFU_PYTHON 不可用(需 3.10+ 且带 SSL: $KEFU_PYTHON"
echo " 详情: $(python_brief "$KEFU_PYTHON")"
echo " 运行 ./install.sh --diagnose 查看全部候选"
exit 1
fi
PYTHON="$KEFU_PYTHON"
else
if ! PYTHON="$(select_python)"; then
print_diagnose
echo "[错误] 未找到可用的 Python 3.10+(需带 SSL 模块)。"
echo
if [ "$AUTO_BUILD" = "1" ] || [ "$AUTO_BUILD" = "yes" ]; then
PYTHON="$(build_python311)" || exit 1
else
echo " 宝塔用户常见原因: pyporject_evn 里的 Python 编译时缺少 openssl-devel。"
echo
echo " 解决方式(任选):"
echo " 1) 自动编译 Python 3.11:"
echo " AUTO_BUILD_PYTHON=1 ./install.sh"
echo " 2) 宝塔面板卸载 Python 3.11 后执行:"
echo " yum install -y openssl openssl-devel && 在面板重装 Python 3.11"
echo " 3) 手动指定已验证可用的 Python:"
echo " KEFU_PYTHON=/path/to/python3.11 ./install.sh"
echo " 4) 查看探测详情:"
echo " ./install.sh --diagnose"
exit 1
fi
fi
fi
echo "[OK] $("$PYTHON" --version) @ $PYTHON"
"$PYTHON" -c "import ssl; print('[OK] OpenSSL:', ssl.OPENSSL_VERSION)"
# ---------- Node.js ----------
if ! command -v node &>/dev/null; then
echo "[警告] 未找到 Node.js,私信签名将无法工作"
echo " 宝塔: 软件商店 -> Node 版本管理器 -> 安装 Node 18+"
else
echo "[OK] Node $(node --version)"
fi
echo
# ---------- 1. Python venv ----------
echo "[1/6] Python 虚拟环境与 pip 包..."
cd "$ROOT/backend"
VENV_PY=".venv/bin/python"
need_new_venv=0
if [ ! -x "$VENV_PY" ]; then
need_new_venv=1
elif ! try_python "$VENV_PY"; then
echo " 现有 .venv 不符合要求,删除并重建..."
rm -rf .venv
need_new_venv=1
fi
if [ "$need_new_venv" -eq 1 ]; then
echo " 创建 .venv <- $PYTHON"
"$PYTHON" -m venv .venv
fi
try_python "$VENV_PY" || { echo "[错误] .venv 创建失败"; exit 1; }
chmod +x .venv/bin/python .venv/bin/pip 2>/dev/null || true
.venv/bin/python -m pip install -U pip -q
.venv/bin/pip install -r requirements.txt
echo " Python 依赖完成"
echo
# ---------- 2. Playwright ----------
echo "[2/6] Playwright Chromium..."
export PLAYWRIGHT_BROWSERS_PATH="${PLAYWRIGHT_BROWSERS_PATH:-$ROOT/playwright-browsers}"
.venv/bin/python -m playwright install chromium
if [ "$(uname -s)" = "Linux" ]; then
.venv/bin/python -m playwright install-deps chromium 2>/dev/null \
|| echo "[警告] install-deps 失败,可手动以 root 执行"
fi
echo " 路径: $PLAYWRIGHT_BROWSERS_PATH"
echo
# ---------- 3. IM Node 依赖 ----------
echo "[3/6] IM 签名依赖..."
cd "$ROOT/backend/rpa_engine/douyin_im/static"
if [ -f package.json ]; then
npm install --no-fund --no-audit
echo " jsrsasign 完成"
fi
echo
# ---------- 4. 前端依赖 ----------
echo "[4/6] 前端依赖..."
cd "$ROOT/frontend"
if [ -f package.json ]; then
npm install --no-fund --no-audit
echo " 前端 npm 完成"
fi
echo
# ---------- 5. 构建前端 ----------
echo "[5/6] 构建前端..."
if [ -f "$ROOT/frontend/package.json" ]; then
cd "$ROOT/frontend" && npm run build
echo " -> frontend/dist"
fi
echo
# ---------- 6. 校验 ----------
echo "[6/6] 校验..."
cd "$ROOT/backend"
.venv/bin/python -c "import fastapi, uvicorn, playwright, execjs; print(' 核心包 OK')"
[ -f "$ROOT/frontend/dist/index.html" ] && echo " 前端静态 OK" \
|| echo "[警告] 未找到 frontend/dist/index.html"
echo
echo "========================================"
echo " 安装完成"
echo
echo " 启动: ./start_web.sh"
echo " API: ./start_backend.sh"
echo " 地址: http://服务器IP:8000"
echo
echo " 宝塔 Python 项目:"
echo " 项目路径: $ROOT/backend"
echo " 启动命令: bash $ROOT/backend/baota_start.sh"
echo " 初始化: bash $ROOT/backend/baota_init.sh"
echo " 详见: deploy/baota.md"
echo "========================================"