#!/bin/bash BASE_DIR="$(cd "$(dirname "$0")" && pwd)" # 自动检测 conda 安装路径(优先用环境变量,其次用 conda info --base) if [ -z "$CONDA_BASE" ]; then if command -v conda >/dev/null 2>&1; then CONDA_BASE="$(conda info --base 2>/dev/null)" fi fi CONDA_BASE="${CONDA_BASE:-$HOME/miniconda3}" # 初始化 conda(脚本中需要 source 才能用 conda activate) if [ -f "$CONDA_BASE/etc/profile.d/conda.sh" ]; then source "$CONDA_BASE/etc/profile.d/conda.sh" else echo "WARNING: 未找到 conda.sh,请确认 CONDA_BASE=$CONDA_BASE 正确" fi echo "=== 换发型项目部署脚本 ===" echo "BASE_DIR: $BASE_DIR" echo "CONDA_BASE: $CONDA_BASE" echo "" ERRORS=() # 1. 检查前提条件 echo "[1/8] 检查前提条件..." command -v git >/dev/null || { echo " ✗ git 未安装"; ERRORS+=("git"); } command -v conda >/dev/null || { echo " ✗ conda 未安装"; ERRORS+=("conda"); } nvidia-smi >/dev/null 2>&1 || { echo " ✗ NVIDIA 驱动未安装"; ERRORS+=("nvidia-smi"); } if [ ${#ERRORS[@]} -eq 0 ]; then echo " ✓ 前提条件满足" fi # 2. 生成 configure.ini echo "[2/8] 生成 configure.ini..." sed "s|__BASE_DIR__|$BASE_DIR|g" "$BASE_DIR/hair_service_sd/config/configure.ini.template" > "$BASE_DIR/hair_service_sd/config/configure.ini" echo " ✓ configure.ini 已生成" # 3. 恢复 conda 环境(conda-pack) echo "[3/8] 恢复 conda 环境(my_hair, sdwebui, kohya)..." for env_name in my_hair sdwebui kohya; do if [ -f "$BASE_DIR/conda_envs/${env_name}.tar.gz" ]; then echo " 恢复 $env_name ..." rm -rf "$CONDA_BASE/envs/$env_name" mkdir -p "$CONDA_BASE/envs/$env_name" tar -xzf "$BASE_DIR/conda_envs/${env_name}.tar.gz" -C "$CONDA_BASE/envs/$env_name" conda activate "$env_name" 2>/dev/null conda-unpack 2>/dev/null # 修复打包后的硬编码路径 conda deactivate 2>/dev/null echo " ✓ $env_name 已恢复" else echo " ✗ conda_envs/${env_name}.tar.gz 不存在,请从网盘下载" ERRORS+=("conda_envs/${env_name}.tar.gz") fi done # 4. 创建 py310 环境(从 yml) echo "[4/8] 创建 py310 环境(从 yml)..." if [ -f "$BASE_DIR/conda_envs/py310.yml" ]; then conda env create -f "$BASE_DIR/conda_envs/py310.yml" -n py310 2>/dev/null && echo " ✓ py310 已创建" || echo " ℹ py310 环境已存在,跳过" else echo " ✗ conda_envs/py310.yml 不存在" ERRORS+=("conda_envs/py310.yml") fi # 5. 检查模型/数据目录 echo "[5/8] 检查模型和数据目录..." for dir in hair_service_sd/weights stable-diffusion-webui/models/Lora stable-diffusion-webui/models/Stable-diffusion stable-diffusion-webui/extensions/sd-webui-controlnet stable-diffusion-webui/repositories kohya_ss_home/.local kohya_ss_home/kohya_ss data/ref_hairstyle; do if [ -d "$BASE_DIR/$dir" ]; then echo " ✓ $dir" else echo " ✗ $dir 缺失,请从网盘下载" ERRORS+=("$dir") fi done # 6. 检查训练底模 echo "[6/8] 检查训练底模 v1-5-pruned-emaonly..." if [ -f "$BASE_DIR/stable-diffusion-webui/models/Stable-diffusion/v1-5-pruned-emaonly.safetensors" ]; then echo " ✓ v1-5-pruned-emaonly.safetensors 已存在" else echo " ✗ v1-5-pruned-emaonly.safetensors 缺失,请从网盘下载 models/ 目录" ERRORS+=("v1-5-pruned-emaonly.safetensors") fi # 7. 创建运行时目录 echo "[7/8] 创建运行时目录..." mkdir -p "$BASE_DIR/logs" mkdir -p "$BASE_DIR/data/tmp" "$BASE_DIR/data/res_dir" "$BASE_DIR/data/userImage" "$BASE_DIR/data/user_info" mkdir -p "$BASE_DIR/kohya_ss_home/train_material" echo " ✓ 运行时目录已创建" # 8. 验证 kohya 训练环境 echo "[8/8] 验证 kohya 训练环境..." KOHYA_PYTHON="$CONDA_BASE/envs/kohya/bin/python" KOHYA_LOCAL="$BASE_DIR/kohya_ss_home/.local/lib/python3.10/site-packages" if [ -f "$KOHYA_PYTHON" ] && [ -d "$KOHYA_LOCAL" ]; then echo " 测试 torch/accelerate 加载..." if PYTHONPATH="$KOHYA_LOCAL" "$KOHYA_PYTHON" -c " import torch, accelerate, bitsandbytes, diffusers print(f' torch={torch.__version__} cuda={torch.cuda.is_available()}') print(f' accelerate={accelerate.__version__}') print(' ✓ 训练环境验证通过') " 2>/dev/null; then true else echo " ✗ 训练环境验证失败,请检查 kohya 环境和 .local 目录" ERRORS+=("kohya验证") fi else echo " ✗ kohya Python 或 .local 目录不存在,跳过验证" ERRORS+=("kohya环境") fi echo "" echo "=== 部署结果 ===" if [ ${#ERRORS[@]} -eq 0 ]; then echo "✓ 所有检查通过,部署完成!" else echo "⚠ 有 ${#ERRORS[@]} 个问题需要处理:" for err in "${ERRORS[@]}"; do echo " - $err" done echo "" echo "请从网盘下载缺失的文件后重新运行 ./setup.sh" fi echo "" echo "启动服务: ./start_all_services.sh"