JCscrew commited on
Commit
eb3127f
·
verified ·
1 Parent(s): f7447df

Create script1.sh

Browse files
Files changed (1) hide show
  1. script1.sh +372 -0
script1.sh ADDED
@@ -0,0 +1,372 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -uo pipefail
3
+ set +H
4
+
5
+ export PIP_NO_CACHE_DIR=1
6
+ export PIP_DISABLE_PIP_VERSION_CHECK=1
7
+ export GIT_TERMINAL_PROMPT=0
8
+
9
+ source /venv/main/bin/activate
10
+ COMFYUI_DIR="${WORKSPACE:-/workspace}/ComfyUI"
11
+ if [ -f "/venv/main/bin/python" ]; then
12
+ PYTHON_BIN="/venv/main/bin/python"
13
+ PIP_BIN="/venv/main/bin/pip"
14
+ else
15
+ PYTHON_BIN="python3"
16
+ PIP_BIN="pip3"
17
+ fi
18
+
19
+ APT_PACKAGES=(
20
+ "aria2"
21
+ )
22
+ PIP_PACKAGES=(
23
+ )
24
+ NODES=(
25
+ "https://github.com/ltdrdata/ComfyUI-Impact-Pack.git"
26
+ "https://github.com/ltdrdata/ComfyUI-Impact-Subpack.git"
27
+ "https://github.com/cubiq/ComfyUI_IPAdapter_plus.git"
28
+ "https://github.com/ka-puna/comfyui-yanc.git"
29
+ "https://github.com/ltdrdata/ComfyUI-Inspire-Pack.git"
30
+ "https://github.com/1038lab/ComfyUI-RMBG.git"
31
+ "https://github.com/godmt/ComfyUI-List-Utils.git"
32
+ "https://github.com/ltdrdata/was-node-suite-comfyui.git"
33
+ )
34
+ BBOX_MODELS=(
35
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/ultralytics/bbox/face_yolov9c.pt"
36
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/ultralytics/bbox/hand_yolov9c.pt"
37
+ )
38
+ CHECKPOINT_MODELS=(
39
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/checkpoints/waiNSFWIllustrious_v150.safetensors"
40
+ )
41
+ CLIP_VISION_MODELS=(
42
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/clip_vision/CLIP-ViT-H-14-laion2B-s32B-b79K.safetensors"
43
+ )
44
+ DINO_MODELS=(
45
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/grounding-dino/groundingdino_swinb_cogcoor.pth"
46
+ )
47
+ IPADAPTER_MODELS=(
48
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/ipadapter/ip-adapter-plus-face_sdxl_vit-h.safetensors"
49
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/ipadapter/ip-adapter-plus_sdxl_vit-h.safetensors"
50
+ )
51
+ RMBG_MODELS=(
52
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/RMBG-2.0/BiRefNet_config.py"
53
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/RMBG-2.0/birefnet.py"
54
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/RMBG-2.0/config.json"
55
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/RMBG/RMBG-2.0/model.safetensors"
56
+ )
57
+ SAM2_MODELS=(
58
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/sam2/sam2.1_hiera_large.safetensors"
59
+ )
60
+ SAMS_MODELS=(
61
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/sams/sam_vit_h_4b8939.pth"
62
+ )
63
+ UPSCALE_MODELS=(
64
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/models/upscale_models/RealESRGAN_x4plus_anime_6B.pth"
65
+ )
66
+ WORKFLOWS=(
67
+ "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/Image_Fixed.json"
68
+ )
69
+
70
+ log_info() { echo "--> $1"; }
71
+ log_warn() { echo " ⚠️ $1"; }
72
+ log_error() { echo " ❌ $1"; }
73
+ log_success() { echo " ✅ $1"; }
74
+ log_step() { echo ""; echo "=== [Step $1] $2 ==="; }
75
+
76
+ package_installed() {
77
+ $PYTHON_BIN -c "import $1" 2>/dev/null && return 0 || return 1
78
+ }
79
+
80
+ filter_requirements() {
81
+ local req_file="$1"
82
+ local tmp_file="${req_file}.filtered"
83
+ > "$tmp_file"
84
+ while IFS= read -r line; do
85
+ [[ -z "$line" || "$line" =~ ^# ]] && continue
86
+ local pkg_name
87
+ pkg_name=$(echo "$line" | sed 's/[<>=!].*//' | xargs)
88
+ if [[ -z "$pkg_name" ]]; then continue; fi
89
+ local module_name="${pkg_name//-/_}"
90
+ if package_installed "$module_name"; then
91
+ log_info "跳過已安裝套件: $pkg_name"
92
+ else
93
+ echo "$line" >> "$tmp_file"
94
+ fi
95
+ done < "$req_file"
96
+ if [ -s "$tmp_file" ]; then
97
+ mv "$tmp_file" "$req_file"
98
+ return 0
99
+ else
100
+ rm -f "$tmp_file"
101
+ log_info "所有套件都已安裝"
102
+ return 1
103
+ fi
104
+ }
105
+
106
+ provisioning_has_valid_hf_token() {
107
+ [[ -n "${HF_TOKEN:-}" ]] || return 1
108
+ local response
109
+ 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")
110
+ [ "$response" -eq 200 ]
111
+ }
112
+
113
+ provisioning_has_valid_civitai_token() {
114
+ [[ -n "${CIVITAI_TOKEN:-}" ]] || return 1
115
+ local response
116
+ 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")
117
+ [ "$response" -eq 200 ]
118
+ }
119
+
120
+ install_node() {
121
+ local repo_url="$1"
122
+ local repo_name
123
+ repo_name=$(basename "$repo_url" .git)
124
+ local install_path="${COMFYUI_DIR}/custom_nodes/${repo_name}"
125
+
126
+ if [ -d "$install_path" ]; then
127
+ if [[ "${AUTO_UPDATE:-true}" != "false" ]]; then
128
+ log_info "更新節點: $repo_name"
129
+ (cd "$install_path" && git pull -q 2>&1 | grep -v "Already up to date" || true)
130
+ else
131
+ log_info "'$repo_name' 已存在,跳過"
132
+ return
133
+ fi
134
+ else
135
+ log_info "克隆節點: $repo_name"
136
+ git clone --depth 1 --single-branch "$repo_url" "$install_path" -q 2>&1 || true
137
+ fi
138
+
139
+ if [ -f "$install_path/requirements.txt" ]; then
140
+ log_info "處理 $repo_name 的依賴..."
141
+ sed -i -e '/^torch/d' -e '/^sam2/d' "$install_path/requirements.txt" 2>/dev/null || true
142
+ if filter_requirements "$install_path/requirements.txt"; then
143
+ log_info "安裝 $repo_name 的新依賴..."
144
+ $PIP_BIN install -q --no-cache-dir -r "$install_path/requirements.txt" 2>&1 | grep -v "Requirement already satisfied" || log_warn "部分依賴安裝失敗"
145
+ fi
146
+ fi
147
+
148
+ if [ -f "$install_path/install.py" ]; then
149
+ log_info "運行 $repo_name 的安裝腳本..."
150
+ $PYTHON_BIN "$install_path/install.py" 2>&1 || log_warn "安裝腳本執行失敗"
151
+ fi
152
+ }
153
+
154
+ download_file() {
155
+ local dest_path="$1"
156
+ local url="$2"
157
+ local filename
158
+ filename=$(basename "$dest_path")
159
+ local tmp_path="${dest_path}.tmp"
160
+
161
+ mkdir -p "$(dirname "$dest_path")"
162
+ if [ -s "$dest_path" ]; then
163
+ log_info "檔案 '$filename' 已存在且完整,跳過下載"
164
+ return 0
165
+ fi
166
+
167
+ log_info "下載: $filename"
168
+ local max_retries=3
169
+ local attempt=0
170
+ local auth_header=""
171
+ local success=1
172
+
173
+ if [[ "$url" =~ huggingface\.co ]] && provisioning_has_valid_hf_token; then
174
+ auth_header="Authorization: Bearer $HF_TOKEN"
175
+ log_info "使用 HuggingFace Token"
176
+ elif [[ "$url" =~ civitai\.com ]] && provisioning_has_valid_civitai_token; then
177
+ auth_header="Authorization: Bearer $CIVITAI_TOKEN"
178
+ log_info "使用 CivitAI Token"
179
+ fi
180
+
181
+ while [ "$attempt" -lt "$max_retries" ]; do
182
+ attempt=$((attempt + 1))
183
+ [ "$attempt" -gt 1 ] && sleep 10
184
+ if command -v aria2c >/dev/null 2>&1; then
185
+ log_info "使用 aria2c (3 線程) 下載: $filename (嘗試 $attempt/$max_retries)"
186
+ 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")
187
+ [[ -n "$auth_header" ]] && aria_opts+=(--header="$auth_header")
188
+ aria2c "${aria_opts[@]}" "$url"
189
+ if [ $? -eq 0 ]; then success=0; break; fi
190
+ else
191
+ log_info "使用 wget 下載: $filename (嘗試 $attempt/$max_retries)"
192
+ local wget_opts=(-O "$tmp_path" -c --timeout=60 --tries=3 --content-disposition --show-progress)
193
+ [[ -n "$auth_header" ]] && wget_opts+=(--header="$auth_header")
194
+ wget "${wget_opts[@]}" "$url"
195
+ if [ $? -eq 0 ]; then success=0; break; fi
196
+ fi
197
+ done
198
+
199
+ if [ "$success" -eq 0 ] && [ -s "$tmp_path" ]; then
200
+ mv "$tmp_path" "$dest_path"
201
+ log_success "下載完成: $filename"
202
+ return 0
203
+ else
204
+ log_error "下載失敗: $filename"
205
+ rm -f "$tmp_path"
206
+ return 1
207
+ fi
208
+ }
209
+
210
+ download_to_directory() {
211
+ local dest_dir="$1"; shift; local urls=("$@")
212
+ if [ ${#urls[@]} -eq 0 ]; then return 0; fi
213
+ mkdir -p "$dest_dir"
214
+ log_info "下載 ${#urls[@]} 個文件到 $dest_dir"
215
+ local MAX_PARALLEL=3
216
+ for url in "${urls[@]}"; do
217
+ while [ $(jobs -r | wc -l) -ge $MAX_PARALLEL ]; do sleep 1; done
218
+ local filename
219
+ filename=$(basename "$url" | sed 's/?.*//')
220
+ download_file "${dest_dir}/${filename}" "$url" &
221
+ done
222
+ wait
223
+ }
224
+
225
+ verify_and_retry_downloads() {
226
+ local dest_dir="$1"; shift; local urls=("$@")
227
+ if [ ${#urls[@]} -eq 0 ]; then return 0; fi
228
+ log_info "檢查 $dest_dir 中的文件..."
229
+ local missing_files=()
230
+ for url in "${urls[@]}"; do
231
+ local filename
232
+ filename=$(basename "$url" | sed 's/?.*//')
233
+ local dest_path="${dest_dir}/${filename}"
234
+ if [ ! -s "$dest_path" ]; then
235
+ log_warn "檔案缺失或不完整: $filename"
236
+ missing_files+=("$url")
237
+ fi
238
+ done
239
+ if [ ${#missing_files[@]} -gt 0 ]; then
240
+ log_warn "發現 ${#missing_files[@]} 個缺失/不完整文件,重新下載..."
241
+ download_to_directory "$dest_dir" "${missing_files[@]}"
242
+ else
243
+ log_success "所有文件已確認存在且完整"
244
+ fi
245
+ }
246
+
247
+ provisioning_print_header() {
248
+ echo ""; echo "##############################################"
249
+ echo "# #"
250
+ echo "# Provisioning Container #"
251
+ echo "# #"
252
+ echo "# This will take some time #"
253
+ echo "# #"
254
+ echo "##############################################"; echo ""
255
+ }
256
+
257
+ provisioning_print_end() {
258
+ echo ""; echo "##############################################"
259
+ echo "# #"
260
+ echo "# Provisioning Complete! #"
261
+ echo "# #"
262
+ echo "# Total time: $((END_TIME - START_TIME)) seconds #"
263
+ echo "# #"
264
+ echo "##############################################"; echo ""
265
+ }
266
+
267
+ provisioning_step1_install_core_deps() {
268
+ log_step "1" "安裝系統與 ComfyUI 核心依賴"
269
+ if [ ${#APT_PACKAGES[@]} -gt 0 ]; then
270
+ log_info "準備安裝 ${#APT_PACKAGES[@]} 個系統套件..."
271
+ local packages_to_install=()
272
+ for pkg in "${APT_PACKAGES[@]}"; do
273
+ if ! dpkg -s "$pkg" >/dev/null 2>&1; then
274
+ packages_to_install+=("$pkg")
275
+ else
276
+ log_success "$pkg 已安裝,跳過"
277
+ fi
278
+ done
279
+ if [ ${#packages_to_install[@]} -gt 0 ]; then
280
+ log_info "正在安裝: ${packages_to_install[*]}"
281
+ apt-get update -qq && apt-get install -y -qq "${packages_to_install[@]}" && log_success "系統套件安裝完成" || log_warn "部分系統套件安裝失敗"
282
+ fi
283
+ fi
284
+
285
+ local comfyui_req_file="${COMFYUI_DIR}/requirements.txt"
286
+ if [ -f "$comfyui_req_file" ]; then
287
+ log_info "處理 ComfyUI 核心依賴: $comfyui_req_file"
288
+ if filter_requirements "$comfyui_req_file"; then
289
+ log_info "安裝 ComfyUI 的新依賴..."
290
+ $PIP_BIN install -q --no-cache-dir -r "$comfyui_req_file" 2>&1 | grep -v "Requirement already satisfied" || log_warn "ComfyUI 部分核心依賴安裝失敗"
291
+ fi
292
+ else
293
+ log_warn "找不到 ComfyUI 的核心 requirements.txt 文件!"
294
+ fi
295
+ }
296
+
297
+ provisioning_step2_nodes() {
298
+ log_step "2" "安裝節點與額外套件"
299
+ if [ ${#NODES[@]} -gt 0 ]; then
300
+ cd "${COMFYUI_DIR}/custom_nodes" || exit 1
301
+ log_info "並行安裝 ${#NODES[@]} 個節點..."
302
+ local MAX_PARALLEL=2
303
+ for node in "${NODES[@]}"; do
304
+ while [ $(jobs -r | wc -l) -ge $MAX_PARALLEL ]; do sleep 1; done
305
+ install_node "$node" &
306
+ done
307
+ wait
308
+ log_success "節點安裝完成"
309
+ cd "${COMFYUI_DIR}" || exit 1
310
+ fi
311
+ }
312
+
313
+ provisioning_step3_downloads() {
314
+ log_step "3" "下載模型與工作流文件"
315
+ download_to_directory "${COMFYUI_DIR}/models/checkpoints" "${CHECKPOINT_MODELS[@]}"
316
+ download_to_directory "${COMFYUI_DIR}/models/clip_vision" "${CLIP_VISION_MODELS[@]}"
317
+ download_to_directory "${COMFYUI_DIR}/models/grounding-dino" "${DINO_MODELS[@]}"
318
+ download_to_directory "${COMFYUI_DIR}/models/ipadapter" "${IPADAPTER_MODELS[@]}"
319
+ download_to_directory "${COMFYUI_DIR}/models/RMBG/RMBG-2.0" "${RMBG_MODELS[@]}"
320
+ download_to_directory "${COMFYUI_DIR}/models/RMBG/segformer_fashion" "${FASHION_MODELS[@]}"
321
+ download_to_directory "${COMFYUI_DIR}/models/sam2" "${SAM2_MODELS[@]}"
322
+ download_to_directory "${COMFYUI_DIR}/models/sams" "${SAMS_MODELS[@]}"
323
+ download_to_directory "${COMFYUI_DIR}/models/ultralytics/bbox" "${BBOX_MODELS[@]}"
324
+ download_to_directory "${COMFYUI_DIR}/models/upscale_models" "${UPSCALE_MODELS[@]}"
325
+ if [ ${#WORKFLOWS[@]} -gt 0 ]; then
326
+ log_info "下載工作流文件..."
327
+ download_to_directory "${COMFYUI_DIR}/user/default/workflows" "${WORKFLOWS[@]}"
328
+ fi
329
+ }
330
+
331
+ if [ -f "/workspace/.provision_complete" ]; then
332
+ log_success "環境已配置,跳過重複執行"
333
+ log_info "如需重新配置,請刪除 /workspace/.provision_complete"
334
+ exit 0
335
+ fi
336
+ if [[ -f /.noprovisioning ]]; then
337
+ log_warn "檢測到 /.noprovisioning 文件,跳過配置"
338
+ exit 0
339
+ fi
340
+
341
+ START_TIME=$(date +%s)
342
+ provisioning_print_header
343
+ cd "${COMFYUI_DIR}" || exit 1
344
+
345
+ provisioning_step1_install_core_deps
346
+
347
+ provisioning_step2_nodes &
348
+ NODE_PID=$!
349
+ provisioning_step3_downloads
350
+ wait $NODE_PID
351
+
352
+ log_step "4" "驗證下載完整性"
353
+ verify_and_retry_downloads "${COMFYUI_DIR}/models/checkpoints" "${CHECKPOINT_MODELS[@]}"
354
+ verify_and_retry_downloads "${COMFYUI_DIR}/models/clip_vision" "${CLIP_VISION_MODELS[@]}"
355
+ verify_and_retry_downloads "${COMFYUI_DIR}/models/grounding-dino" "${DINO_MODELS[@]}"
356
+ verify_and_retry_downloads "${COMFYUI_DIR}/models/ipadapter" "${IPADAPTER_MODELS[@]}"
357
+ verify_and_retry_downloads "${COMFYUI_DIR}/models/RMBG/RMBG-2.0" "${RMBG_MODELS[@]}"
358
+ verify_and_retry_downloads "${COMFYUI_DIR}/models/RMBG/segformer_fashion" "${FASHION_MODELS[@]}"
359
+ verify_and_retry_downloads "${COMFYUI_DIR}/models/sam2" "${SAM2_MODELS[@]}"
360
+ verify_and_retry_downloads "${COMFYUI_DIR}/models/sams" "${SAMS_MODELS[@]}"
361
+ verify_and_retry_downloads "${COMFYUI_DIR}/models/ultralytics/bbox" "${BBOX_MODELS[@]}"
362
+ verify_and_retry_downloads "${COMFYUI_DIR}/models/upscale_models" "${UPSCALE_MODELS[@]}"
363
+ verify_and_retry_downloads "${COMFYUI_DIR}/user/default/workflows" "${WORKFLOWS[@]}"
364
+
365
+ log_step "5" "完成配置"
366
+ touch "/workspace/.provision_complete"
367
+ log_success "配置標記文件已創建"
368
+
369
+ END_TIME=$(date +%s)
370
+ provisioning_print_end
371
+ log_success "所有配置步驟已完成!"
372
+ exit 0