RisuAI_asset_generator / script_nightly2.sh
JCscrew's picture
Update script_nightly2.sh
2f3c990 verified
raw
history blame
15.8 kB
#!/bin/bash
set -uo pipefail
set +H
export PIP_NO_CACHE_DIR=1
export PIP_DISABLE_PIP_VERSION_CHECK=1
export GIT_TERMINAL_PROMPT=0
source /venv/main/bin/activate
COMFYUI_DIR="${WORKSPACE:-/workspace}/ComfyUI"
if [ -f "/venv/main/bin/python" ]; then
PYTHON_BIN="/venv/main/bin/python"
PIP_BIN="/venv/main/bin/pip"
else
PYTHON_BIN="python3"
PIP_BIN="pip3"
fi
APT_PACKAGES=(
"aria2"
)
PIP_PACKAGES=(
)
NODES=(
"https://github.com/ltdrdata/ComfyUI-Impact-Pack.git"
"https://github.com/ltdrdata/ComfyUI-Impact-Subpack.git"
"https://github.com/cubiq/ComfyUI_IPAdapter_plus.git"
"https://github.com/ka-puna/comfyui-yanc.git"
"https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git"
"https://github.com/1038lab/ComfyUI-RMBG.git"
"https://github.com/godmt/ComfyUI-List-Utils.git"
"https://github.com/ltdrdata/was-node-suite-comfyui.git"
)
BBOX_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/ultralytics/bbox/face_yolov9c.pt"
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/ultralytics/bbox/hand_yolov9c.pt"
)
CHECKPOINT_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/checkpoints/waiNSFWIllustrious_v150.safetensors"
)
CLIP_VISION_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/clip_vision/CLIP-ViT-H-14-laion2B-s32B-b79K.safetensors"
)
DINO_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/grounding-dino/groundingdino_swinb_cogcoor.pth"
)
FASHION_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/segformer_fashion/config.json"
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/segformer_fashion/model.safetensors"
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/segformer_fashion/preprocessor_config.json"
)
IPADAPTER_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/ipadapter/ip-adapter-plus-face_sdxl_vit-h.safetensors"
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/ipadapter/ip-adapter-plus_sdxl_vit-h.safetensors"
)
LORAS_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/loras/Better_detailed_pussy_and_anus_v3.0.safetensors"
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/loras/Hugkissingbreast_press_pov_Illustrious-000005.safetensors"
)
RMBG_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/RMBG-2.0/BiRefNet_config.py"
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/RMBG-2.0/birefnet.py"
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/RMBG-2.0/config.json"
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/RMBG-2.0/model.safetensors"
)
SAM2_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/sam2/sam2.1_hiera_large.safetensors"
)
SAMS_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/sams/sam_vit_h_4b8939.pth"
)
UPSCALE_MODELS=(
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/upscale_models/RealESRGAN_x4plus_anime_6B.pth"
"https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/upscale_models/4x-UltraSharpV2_Lite.pth"
)
WORKFLOWS=
WORKFLOWS=(
)
log_info() { echo "--> $1"; }
log_warn() { echo " ⚠️ $1"; }
log_error() { echo " ❌ $1"; }
log_success() { echo " ✅ $1"; }
log_step() { echo ""; echo "=== [Step $1] $2 ==="; }
package_installed() {
$PYTHON_BIN -c "import $1" 2>/dev/null && return 0 || return 1
}
filter_requirements() {
local req_file="$1"
local tmp_file="${req_file}.filtered"
> "$tmp_file"
while IFS= read -r line; do
[[ -z "$line" || "$line" =~ ^# ]] && continue
local pkg_name
pkg_name=$(echo "$line" | sed 's/[<>=!].*//' | xargs)
if [[ -z "$pkg_name" ]]; then continue; fi
local module_name="${pkg_name//-/_}"
if package_installed "$module_name"; then
log_info "跳過已安裝套件: $pkg_name"
else
echo "$line" >> "$tmp_file"
fi
done < "$req_file"
if [ -s "$tmp_file" ]; then
mv "$tmp_file" "$req_file"
return 0
else
rm -f "$tmp_file"
log_info "所有套件都已安裝"
return 1
fi
}
provisioning_has_valid_hf_token() {
[[ -n "${HF_TOKEN:-}" ]] || return 1
local response
response=$(curl -o /dev/null -s -w "%{http_code}" -X GET "https://huggingface.co/api/whoami-v2" -H "Authorization: Bearer $HF_TOKEN" -H "Content-Type: application/json")
[ "$response" -eq 200 ]
}
provisioning_has_valid_civitai_token() {
[[ -n "${CIVITAI_TOKEN:-}" ]] || return 1
local response
response=$(curl -o /dev/null -s -w "%{http_code}" -X GET "https://civitai.com/api/v1/models?hidden=1&limit=1" -H "Authorization: Bearer $CIVITAI_TOKEN" -H "Content-Type: application/json")
[ "$response" -eq 200 ]
}
install_node() {
local repo_url="$1"
local repo_name
repo_name=$(basename "$repo_url" .git)
local install_path="${COMFYUI_DIR}/custom_nodes/${repo_name}"
if [ -d "$install_path" ]; then
if [[ "${AUTO_UPDATE:-true}" != "false" ]]; then
log_info "更新節點: $repo_name"
(cd "$install_path" && git pull -q 2>&1 | grep -v "Already up to date" || true)
else
log_info "'$repo_name' 已存在,跳過"
return
fi
else
log_info "克隆節點: $repo_name"
git clone --depth 1 --single-branch "$repo_url" "$install_path" -q 2>&1 || true
fi
if [ -f "$install_path/requirements.txt" ]; then
log_info "處理 $repo_name 的依賴..."
sed -i -e '/^torch/d' -e '/^sam2/d' "$install_path/requirements.txt" 2>/dev/null || true
if filter_requirements "$install_path/requirements.txt"; then
log_info "安裝 $repo_name 的新依賴..."
$PIP_BIN install -q --no-cache-dir -r "$install_path/requirements.txt" 2>&1 | grep -v "Requirement already satisfied" || log_warn "部分依賴安裝失敗"
fi
fi
if [ -f "$install_path/install.py" ]; then
log_info "運行 $repo_name 的安裝腳本..."
$PYTHON_BIN "$install_path/install.py" 2>&1 || log_warn "安裝腳本執行失敗"
fi
}
download_file() {
local dest_path="$1"
local url="$2"
local filename
filename=$(basename "$dest_path")
local tmp_path="${dest_path}.tmp"
mkdir -p "$(dirname "$dest_path")"
if [ -s "$dest_path" ]; then
log_info "檔案 '$filename' 已存在且完整,跳過下載"
return 0
fi
log_info "下載: $filename"
local max_retries=3
local attempt=0
local auth_header=""
local success=1
if [[ "$url" =~ huggingface\.co ]] && provisioning_has_valid_hf_token; then
auth_header="Authorization: Bearer $HF_TOKEN"
log_info "使用 HuggingFace Token"
elif [[ "$url" =~ civitai\.com ]] && provisioning_has_valid_civitai_token; then
auth_header="Authorization: Bearer $CIVITAI_TOKEN"
log_info "使用 CivitAI Token"
fi
while [ "$attempt" -lt "$max_retries" ]; do
attempt=$((attempt + 1))
[ "$attempt" -gt 1 ] && sleep 10
if command -v aria2c >/dev/null 2>&1; then
log_info "使用 aria2c (3 線程) 下載: $filename (嘗試 $attempt/$max_retries)"
local aria_opts=(--console-log-level=error -c -x 3 -s 3 -k 1M --max-connection-per-server=3 --max-tries=3 --retry-wait=5 --timeout=180 --file-allocation=falloc --auto-file-renaming=false -d "$(dirname "$dest_path")" -o "${filename}.tmp")
[[ -n "$auth_header" ]] && aria_opts+=(--header="$auth_header")
aria2c "${aria_opts[@]}" "$url"
if [ $? -eq 0 ]; then success=0; break; fi
else
log_info "使用 wget 下載: $filename (嘗試 $attempt/$max_retries)"
local wget_opts=(-O "$tmp_path" -c --timeout=60 --tries=3 --content-disposition --show-progress)
[[ -n "$auth_header" ]] && wget_opts+=(--header="$auth_header")
wget "${wget_opts[@]}" "$url"
if [ $? -eq 0 ]; then success=0; break; fi
fi
done
if [ "$success" -eq 0 ] && [ -s "$tmp_path" ]; then
mv "$tmp_path" "$dest_path"
log_success "下載完成: $filename"
return 0
else
log_error "下載失敗: $filename"
rm -f "$tmp_path"
return 1
fi
}
download_to_directory() {
local dest_dir="$1"; shift; local urls=("$@")
if [ ${#urls[@]} -eq 0 ]; then return 0; fi
mkdir -p "$dest_dir"
log_info "下載 ${#urls[@]} 個文件到 $dest_dir"
local MAX_PARALLEL=3
for url in "${urls[@]}"; do
while [ $(jobs -r | wc -l) -ge $MAX_PARALLEL ]; do sleep 1; done
local filename
filename=$(basename "$url" | sed 's/?.*//')
download_file "${dest_dir}/${filename}" "$url" &
done
wait
}
verify_and_retry_downloads() {
local dest_dir="$1"; shift; local urls=("$@")
if [ ${#urls[@]} -eq 0 ]; then return 0; fi
log_info "檢查 $dest_dir 中的文件..."
local missing_files=()
for url in "${urls[@]}"; do
local filename
filename=$(basename "$url" | sed 's/?.*//')
local dest_path="${dest_dir}/${filename}"
if [ ! -s "$dest_path" ]; then
log_warn "檔案缺失或不完整: $filename"
missing_files+=("$url")
fi
done
if [ ${#missing_files[@]} -gt 0 ]; then
log_warn "發現 ${#missing_files[@]} 個缺失/不完整文件,重新下載..."
download_to_directory "$dest_dir" "${missing_files[@]}"
else
log_success "所有文件已確認存在且完整"
fi
}
provisioning_print_header() {
echo ""; echo "##############################################"
echo "# #"
echo "# Provisioning Container #"
echo "# #"
echo "# This will take some time #"
echo "# #"
echo "##############################################"; echo ""
}
provisioning_print_end() {
echo ""; echo "##############################################"
echo "# #"
echo "# Provisioning Complete! #"
echo "# #"
echo "# Total time: $((END_TIME - START_TIME)) seconds #"
echo "# #"
echo "##############################################"; echo ""
}
provisioning_step1_install_core_deps() {
log_step "1" "安裝系統與 ComfyUI 核心依賴"
if [ ${#APT_PACKAGES[@]} -gt 0 ]; then
log_info "準備安裝 ${#APT_PACKAGES[@]} 個系統套件..."
local packages_to_install=()
for pkg in "${APT_PACKAGES[@]}"; do
if ! dpkg -s "$pkg" >/dev/null 2>&1; then
packages_to_install+=("$pkg")
else
log_success "$pkg 已安裝,跳過"
fi
done
if [ ${#packages_to_install[@]} -gt 0 ]; then
log_info "正在安裝: ${packages_to_install[*]}"
apt-get update -qq && apt-get install -y -qq "${packages_to_install[@]}" && log_success "系統套件安裝完成" || log_warn "部分系統套件安裝失敗"
fi
fi
local comfyui_req_file="${COMFYUI_DIR}/requirements.txt"
if [ -f "$comfyui_req_file" ]; then
log_info "處理 ComfyUI 核心依賴: $comfyui_req_file"
if filter_requirements "$comfyui_req_file"; then
log_info "安裝 ComfyUI 的新依賴..."
$PIP_BIN install -q --no-cache-dir -r "$comfyui_req_file" 2>&1 | grep -v "Requirement already satisfied" || log_warn "ComfyUI 部分核心依賴安裝失敗"
fi
else
log_warn "找不到 ComfyUI 的核心 requirements.txt 文件!"
fi
}
provisioning_step2_nodes() {
log_step "2" "安裝節點與額外套件"
if [ ${#NODES[@]} -gt 0 ]; then
cd "${COMFYUI_DIR}/custom_nodes" || exit 1
log_info "並行安裝 ${#NODES[@]} 個節點..."
local MAX_PARALLEL=2
for node in "${NODES[@]}"; do
while [ $(jobs -r | wc -l) -ge $MAX_PARALLEL ]; do sleep 1; done
install_node "$node" &
done
wait
log_success "節點安裝完成"
cd "${COMFYUI_DIR}" || exit 1
fi
}
provisioning_step3_downloads() {
log_step "3" "下載模型與工作流文件"
download_to_directory "${COMFYUI_DIR}/models/checkpoints" "${CHECKPOINT_MODELS[@]}"
download_to_directory "${COMFYUI_DIR}/models/clip_vision" "${CLIP_VISION_MODELS[@]}"
download_to_directory "${COMFYUI_DIR}/models/grounding-dino" "${DINO_MODELS[@]}"
download_to_directory "${COMFYUI_DIR}/models/ipadapter" "${IPADAPTER_MODELS[@]}"
download_to_directory "${COMFYUI_DIR}/models/loras" "${LORAS_MODELS[@]}"
download_to_directory "${COMFYUI_DIR}/models/RMBG/RMBG-2.0" "${RMBG_MODELS[@]}"
download_to_directory "${COMFYUI_DIR}/models/RMBG/segformer_fashion" "${FASHION_MODELS[@]}"
download_to_directory "${COMFYUI_DIR}/models/sam2" "${SAM2_MODELS[@]}"
download_to_directory "${COMFYUI_DIR}/models/sams" "${SAMS_MODELS[@]}"
download_to_directory "${COMFYUI_DIR}/models/ultralytics/bbox" "${BBOX_MODELS[@]}"
download_to_directory "${COMFYUI_DIR}/models/upscale_models" "${UPSCALE_MODELS[@]}"
if [ ${#WORKFLOWS[@]} -gt 0 ]; then
log_info "下載工作流文件..."
download_to_directory "${COMFYUI_DIR}/user/default/workflows" "${WORKFLOWS[@]}"
fi
}
if [ -f "/workspace/.provision_complete" ]; then
log_success "環境已配置,跳過重複執行"
log_info "如需重新配置,請刪除 /workspace/.provision_complete"
exit 0
fi
if [[ -f /.noprovisioning ]]; then
log_warn "檢測到 /.noprovisioning 文件,跳過配置"
exit 0
fi
START_TIME=$(date +%s)
provisioning_print_header
cd "${COMFYUI_DIR}" || exit 1
provisioning_step1_install_core_deps
provisioning_step2_nodes &
NODE_PID=$!
provisioning_step3_downloads
wait $NODE_PID
log_step "4" "驗證下載完整性"
verify_and_retry_downloads "${COMFYUI_DIR}/models/checkpoints" "${CHECKPOINT_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/models/clip_vision" "${CLIP_VISION_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/models/grounding-dino" "${DINO_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/models/ipadapter" "${IPADAPTER_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/models/loras" "${LORAS_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/models/RMBG/RMBG-2.0" "${RMBG_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/models/RMBG/segformer_fashion" "${FASHION_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/models/sam2" "${SAM2_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/models/sams" "${SAMS_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/models/ultralytics/bbox" "${BBOX_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/models/upscale_models" "${UPSCALE_MODELS[@]}"
verify_and_retry_downloads "${COMFYUI_DIR}/user/default/workflows" "${WORKFLOWS[@]}"
log_step "5" "完成配置"
touch "/workspace/.provision_complete"
log_success "配置標記文件已創建"
END_TIME=$(date +%s)
provisioning_print_end
log_success "所有配置步驟已完成!"
exit 0