JCscrew commited on
Commit
1ccab35
·
verified ·
1 Parent(s): 851be8d

Update script.sh

Browse files
Files changed (1) hide show
  1. script.sh +102 -95
script.sh CHANGED
@@ -45,7 +45,6 @@ WORKFLOWS=(
45
  "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/Single_Posture.json"
46
  )
47
 
48
- # ===== 新增:已知內建套件列表(vastai/comfy image已包含) =====
49
  PREINSTALLED_PACKAGES=(
50
  "torch"
51
  "torchvision"
@@ -65,12 +64,10 @@ log_error() { echo " ❌ $1"; }
65
  log_success() { echo " ✅ $1"; }
66
  log_step() { echo ""; echo "=== [Step $1] $2 ==="; }
67
 
68
- # ===== 新增:檢查套件是否已安裝 =====
69
  package_installed() {
70
  $PYTHON_BIN -c "import $1" 2>/dev/null && return 0 || return 1
71
  }
72
 
73
- # ===== 新增:過濾requirements.txt中已安裝的套件 =====
74
  filter_requirements() {
75
  local req_file="$1"
76
  local tmp_file="${req_file}.filtered"
@@ -78,10 +75,8 @@ filter_requirements() {
78
  > "$tmp_file"
79
 
80
  while IFS= read -r line; do
81
- # 跳過空行和註解
82
  [[ -z "$line" || "$line" =~ ^# ]] && continue
83
 
84
- # 提取套件名(處理版本指定符如==, >=等)
85
  local pkg_name
86
  pkg_name=$(echo "$line" | sed 's/[<>=!].*//' | xargs)
87
 
@@ -89,7 +84,6 @@ filter_requirements() {
89
  continue
90
  fi
91
 
92
- # 轉換為module名稱(- 轉 _)
93
  local module_name="${pkg_name//-/_}"
94
 
95
  if package_installed "$module_name"; then
@@ -175,10 +169,8 @@ install_node() {
175
  if [ -f "$install_path/requirements.txt" ]; then
176
  log_info "處理 $repo_name 的依賴..."
177
 
178
- # 移除torch相關套件(避免重複安裝)
179
  sed -i -e '/^torch/d' -e '/^sam2/d' "$install_path/requirements.txt" 2>/dev/null || true
180
 
181
- # 過濾已安裝的套件
182
  if filter_requirements "$install_path/requirements.txt"; then
183
  log_info "安裝 $repo_name 的新依賴..."
184
  $PIP_BIN install -q --no-cache-dir -r "$install_path/requirements.txt" 2>&1 | grep -v "Requirement already satisfied" || log_warn "部分依賴安裝失敗"
@@ -199,12 +191,7 @@ download_file() {
199
 
200
  mkdir -p "$(dirname "$dest_path")"
201
 
202
- if [ -f "$dest_path" ]; then
203
- log_info "檔案 '$filename' 已存在,跳過下載"
204
- return 0
205
- fi
206
-
207
- log_info "下載: $filename"
208
 
209
  local max_retries=3
210
  local attempt=0
@@ -256,7 +243,7 @@ download_file() {
256
  done
257
 
258
  if [ -f "$dest_path" ]; then
259
- log_success "下載完成: $filename"
260
  return 0
261
  else
262
  log_error "下載失敗: $filename"
@@ -264,57 +251,62 @@ download_file() {
264
  fi
265
  }
266
 
267
- download_to_directory() {
268
  local dest_dir="$1"
269
  shift
270
  local urls=("$@")
271
 
272
- if [ ${#urls[@]} -eq 0 ]; then
273
- return 0
274
- fi
275
-
276
  mkdir -p "$dest_dir"
277
- log_info "下載 ${#urls[@]} 個文件到 $dest_dir"
278
-
279
- local MAX_PARALLEL=3
280
- for url in "${urls[@]}"; do
281
- while [ $(jobs -r | wc -l) -ge $MAX_PARALLEL ]; do
282
- sleep 1
283
- done
284
- local filename
285
- filename=$(basename "$url" | sed 's/?.*//')
286
- download_file "${dest_dir}/${filename}" "$url" &
287
- done
288
- wait
289
- }
290
 
291
- verify_and_retry_downloads() {
292
- local dest_dir="$1"
293
- shift
294
- local urls=("$@")
295
-
296
- if [ ${#urls[@]} -eq 0 ]; then
297
- return 0
298
- fi
299
-
300
- log_info "檢查 $dest_dir 中的文件..."
301
-
302
- local missing_files=()
303
  for url in "${urls[@]}"; do
304
  local filename
305
  filename=$(basename "$url" | sed 's/?.*//')
306
  local dest_path="${dest_dir}/${filename}"
307
 
308
- if [ ! -f "$dest_path" ]; then
309
- log_warn "檔案缺失: $filename"
310
- missing_files+=("$url")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  fi
312
  done
313
 
314
- if [ ${#missing_files[@]} -gt 0 ]; then
315
- log_warn "發現 ${#missing_files[@]} 個缺失文件,重新下載..."
316
  local MAX_PARALLEL=3
317
- for url in "${missing_files[@]}"; do
318
  while [ $(jobs -r | wc -l) -ge $MAX_PARALLEL ]; do
319
  sleep 1
320
  done
@@ -323,11 +315,40 @@ verify_and_retry_downloads() {
323
  download_file "${dest_dir}/${filename}" "$url" &
324
  done
325
  wait
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  else
327
- log_success "所有文件已確認存在"
328
  fi
329
  }
330
 
 
331
  provisioning_print_header() {
332
  echo ""
333
  echo "##############################################"
@@ -393,29 +414,18 @@ provisioning_step2_nodes() {
393
  fi
394
  }
395
 
396
- provisioning_step3_downloads() {
397
- log_step "3" "下載模型與工作流文件"
 
 
 
 
 
 
 
398
 
399
- download_to_directory "${COMFYUI_DIR}/models/checkpoints" "${CHECKPOINT_MODELS[@]}"
400
- download_to_directory "${COMFYUI_DIR}/models/clip_vision" "${CLIP_VISION_MODELS[@]}"
401
- download_to_directory "${COMFYUI_DIR}/models/ipadapter" "${IPADAPTER_MODELS[@]}"
402
- download_to_directory "${COMFYUI_DIR}/models/sams" "${SAM_MODELS[@]}"
403
- download_to_directory "${COMFYUI_DIR}/models/ultralytics/bbox" "${ULTRALYTICS_BBOX_MODELS[@]}"
404
- download_to_directory "${COMFYUI_DIR}/models/upscale_models" "${ESRGAN_MODELS[@]}"
405
-
406
  if [ ${#WORKFLOWS[@]} -gt 0 ]; then
407
- log_info "下載工作流文件..."
408
- mkdir -p "${COMFYUI_DIR}/user/default/workflows"
409
- local MAX_PARALLEL=3
410
- for workflow_url in "${WORKFLOWS[@]}"; do
411
- while [ $(jobs -r | wc -l) -ge $MAX_PARALLEL ]; do
412
- sleep 1
413
- done
414
- local workflow_name
415
- workflow_name=$(basename "$workflow_url" | sed 's/?.*//')
416
- download_file "${COMFYUI_DIR}/user/default/workflows/${workflow_name}" "$workflow_url" &
417
- done
418
- wait
419
  fi
420
  }
421
 
@@ -425,37 +435,34 @@ provisioning_print_header
425
 
426
  cd "${COMFYUI_DIR}" || exit 1
427
 
428
- log_step "1" "安裝系統套件 (aria2)"
 
 
 
 
 
 
 
 
429
 
430
- if ! command -v aria2c >/dev/null 2>&1; then
431
- log_info "aria2 未安裝,開始安裝..."
432
  if command -v sudo &>/dev/null && sudo -n true 2>/dev/null; then
433
  sudo apt-get update -qq
434
- sudo apt-get install -y -qq aria2
435
- log_success "aria2 安裝完成"
436
  else
437
- log_warn "無 sudo 權限,無法安裝 aria2 (下載將使用 wget 備用)"
 
438
  fi
439
  else
440
- log_success "aria2 已安裝,跳過"
441
  fi
442
 
443
- # 步驟 2 (安裝節點) 與 步驟 3 (下載模型) 並行執行
444
- provisioning_step2_nodes &
445
- NODE_PID=$!
446
-
447
- provisioning_step3_downloads
448
-
449
- log_step "4" "驗證下載完整性"
450
-
451
- verify_and_retry_downloads "${COMFYUI_DIR}/models/checkpoints" "${CHECKPOINT_MODELS[@]}"
452
- verify_and_retry_downloads "${COMFYUI_DIR}/models/clip_vision" "${CLIP_VISION_MODELS[@]}"
453
- verify_and_retry_downloads "${COMFYUI_DIR}/models/ipadapter" "${IPADAPTER_MODELS[@]}"
454
- verify_and_retry_downloads "${COMFYUI_DIR}/models/sams" "${SAM_MODELS[@]}"
455
- verify_and_retry_downloads "${COMFYUI_DIR}/models/ultralytics/bbox" "${ULTRALYTICS_BBOX_MODELS[@]}"
456
- verify_and_retry_downloads "${COMFYUI_DIR}/models/upscale_models" "${ESRGAN_MODELS[@]}"
457
 
458
- log_step "5" "完成配置"
459
 
460
  touch "/workspace/.provision_complete"
461
  log_success "配置標記文件已創建"
 
45
  "https://huggingface.co/JCscrew/RisuAI_asset_generator/resolve/main/Single_Posture.json"
46
  )
47
 
 
48
  PREINSTALLED_PACKAGES=(
49
  "torch"
50
  "torchvision"
 
64
  log_success() { echo " ✅ $1"; }
65
  log_step() { echo ""; echo "=== [Step $1] $2 ==="; }
66
 
 
67
  package_installed() {
68
  $PYTHON_BIN -c "import $1" 2>/dev/null && return 0 || return 1
69
  }
70
 
 
71
  filter_requirements() {
72
  local req_file="$1"
73
  local tmp_file="${req_file}.filtered"
 
75
  > "$tmp_file"
76
 
77
  while IFS= read -r line; do
 
78
  [[ -z "$line" || "$line" =~ ^# ]] && continue
79
 
 
80
  local pkg_name
81
  pkg_name=$(echo "$line" | sed 's/[<>=!].*//' | xargs)
82
 
 
84
  continue
85
  fi
86
 
 
87
  local module_name="${pkg_name//-/_}"
88
 
89
  if package_installed "$module_name"; then
 
169
  if [ -f "$install_path/requirements.txt" ]; then
170
  log_info "處理 $repo_name 的依賴..."
171
 
 
172
  sed -i -e '/^torch/d' -e '/^sam2/d' "$install_path/requirements.txt" 2>/dev/null || true
173
 
 
174
  if filter_requirements "$install_path/requirements.txt"; then
175
  log_info "安裝 $repo_name 的新依賴..."
176
  $PIP_BIN install -q --no-cache-dir -r "$install_path/requirements.txt" 2>&1 | grep -v "Requirement already satisfied" || log_warn "部分依賴安裝失敗"
 
191
 
192
  mkdir -p "$(dirname "$dest_path")"
193
 
194
+ log_info "開始下載: $filename"
 
 
 
 
 
195
 
196
  local max_retries=3
197
  local attempt=0
 
243
  done
244
 
245
  if [ -f "$dest_path" ]; then
246
+ # Verification will be handled by sync_and_verify, just log success here.
247
  return 0
248
  else
249
  log_error "下載失敗: $filename"
 
251
  fi
252
  }
253
 
254
+ sync_and_verify() {
255
  local dest_dir="$1"
256
  shift
257
  local urls=("$@")
258
 
259
+ if [ ${#urls[@]} -eq 0 ]; then return 0; fi
260
+
261
+ local urls_to_download=()
 
262
  mkdir -p "$dest_dir"
 
 
 
 
 
 
 
 
 
 
 
 
 
263
 
264
+ log_info "開始驗證 $dest_dir 中的文件..."
265
+
 
 
 
 
 
 
 
 
 
 
266
  for url in "${urls[@]}"; do
267
  local filename
268
  filename=$(basename "$url" | sed 's/?.*//')
269
  local dest_path="${dest_dir}/${filename}"
270
 
271
+ local expected_sha256=""
272
+ if [[ "$url" =~ huggingface\.co ]]; then
273
+ expected_sha256=$(curl -sI "$url?lfs=true" | grep -i 'x-linked-sha256' | awk -F': ' '{print $2}' | tr -d '\r')
274
+ fi
275
+
276
+ if [ -z "$expected_sha256" ]; then
277
+ log_warn "無法獲取 '$filename' 的校驗和,將僅檢查文件是否存在。"
278
+ if [ ! -f "$dest_path" ]; then
279
+ log_info "文件不存在,加入下載列表: $filename"
280
+ urls_to_download+=("$url")
281
+ else
282
+ log_success "文件已存在 (跳過校驗): $filename"
283
+ fi
284
+ continue
285
+ fi
286
+
287
+ if [ -f "$dest_path" ]; then
288
+ local local_sha256
289
+ local_sha256=$(sha256sum "$dest_path" | awk '{print $1}')
290
+ if [ "$local_sha256" == "$expected_sha256" ]; then
291
+ log_success "文件校驗通過: $filename"
292
+ else
293
+ log_warn "文件校驗和不匹配: $filename"
294
+ log_warn " --> 預期: $expected_sha256"
295
+ log_warn " --> 得到: $local_sha256"
296
+ rm -f "$dest_path"
297
+ log_info "已刪除損壞文件,將重新下載。"
298
+ urls_to_download+=("$url")
299
+ fi
300
+ else
301
+ log_info "文件不存在,加入下載列表: $filename"
302
+ urls_to_download+=("$url")
303
  fi
304
  done
305
 
306
+ if [ ${#urls_to_download[@]} -gt 0 ]; then
307
+ log_info "準備下載 ${#urls_to_download[@]} 個新文件或無效文件到 $dest_dir"
308
  local MAX_PARALLEL=3
309
+ for url in "${urls_to_download[@]}"; do
310
  while [ $(jobs -r | wc -l) -ge $MAX_PARALLEL ]; do
311
  sleep 1
312
  done
 
315
  download_file "${dest_dir}/${filename}" "$url" &
316
  done
317
  wait
318
+
319
+ log_info "重新驗證下載的文件..."
320
+ for url in "${urls_to_download[@]}"; do
321
+ local filename
322
+ filename=$(basename "$url" | sed 's/?.*//')
323
+ local dest_path="${dest_dir}/${filename}"
324
+
325
+ if [ ! -f "$dest_path" ]; then
326
+ log_error "重試下載後文件依然缺失: $filename"
327
+ continue
328
+ fi
329
+
330
+ local expected_sha256=""
331
+ if [[ "$url" =~ huggingface\.co ]]; then
332
+ expected_sha256=$(curl -sI "$url?lfs=true" | grep -i 'x-linked-sha256' | awk -F': ' '{print $2}' | tr -d '\r')
333
+ fi
334
+
335
+ if [ -n "$expected_sha256" ]; then
336
+ local local_sha256
337
+ local_sha256=$(sha256sum "$dest_path" | awk '{print $1}')
338
+ if [ "$local_sha256" == "$expected_sha256" ]; then
339
+ log_success "重新下載的文件校驗通過: $filename"
340
+ else
341
+ log_error "重新下載的文件校驗失敗: $filename"
342
+ fi
343
+ fi
344
+ done
345
+
346
  else
347
+ log_success "$dest_dir 中的所有文件均已驗證且為最新。"
348
  fi
349
  }
350
 
351
+
352
  provisioning_print_header() {
353
  echo ""
354
  echo "##############################################"
 
414
  fi
415
  }
416
 
417
+ provisioning_step3_models_and_workflows() {
418
+ log_step "3" "下載並驗證模型與工作流"
419
+
420
+ sync_and_verify "${COMFYUI_DIR}/models/checkpoints" "${CHECKPOINT_MODELS[@]}"
421
+ sync_and_verify "${COMFYUI_DIR}/models/clip_vision" "${CLIP_VISION_MODELS[@]}"
422
+ sync_and_verify "${COMFYUI_DIR}/models/ipadapter" "${IPADAPTER_MODELS[@]}"
423
+ sync_and_verify "${COMFYUI_DIR}/models/sams" "${SAM_MODELS[@]}"
424
+ sync_and_verify "${COMFYUI_DIR}/models/ultralytics/bbox" "${ULTRALYTICS_BBOX_MODELS[@]}"
425
+ sync_and_verify "${COMFYUI_DIR}/models/upscale_models" "${ESRGAN_MODELS[@]}"
426
 
 
 
 
 
 
 
 
427
  if [ ${#WORKFLOWS[@]} -gt 0 ]; then
428
+ sync_and_verify "${COMFYUI_DIR}/user/default/workflows" "${WORKFLOWS[@]}"
 
 
 
 
 
 
 
 
 
 
 
429
  fi
430
  }
431
 
 
435
 
436
  cd "${COMFYUI_DIR}" || exit 1
437
 
438
+ log_step "1" "安裝系統套件"
439
+
440
+ COMMANDS_TO_CHECK=("aria2c" "curl" "sha256sum")
441
+ MISSING_COMMANDS=()
442
+ for cmd in "${COMMANDS_TO_CHECK[@]}"; do
443
+ if ! command -v $cmd >/dev/null 2>&1; then
444
+ MISSING_COMMANDS+=($cmd)
445
+ fi
446
+ done
447
 
448
+ if [ ${#MISSING_COMMANDS[@]} -gt 0 ]; then
449
+ log_info "缺少必要套件: ${MISSING_COMMANDS[*]}. 開始安裝..."
450
  if command -v sudo &>/dev/null && sudo -n true 2>/dev/null; then
451
  sudo apt-get update -qq
452
+ sudo apt-get install -y -qq aria2 curl coreutils
453
+ log_success "套件安裝完成"
454
  else
455
+ log_error "無 sudo 權限,無法安裝缺失套件。請手動安裝: ${MISSING_COMMANDS[*]}"
456
+ exit 1
457
  fi
458
  else
459
+ log_success "所有必要套件 (aria2, curl, sha256sum) 均已安裝。"
460
  fi
461
 
462
+ provisioning_step2_nodes
463
+ provisioning_step3_models_and_workflows
 
 
 
 
 
 
 
 
 
 
 
 
464
 
465
+ log_step "4" "完成配置"
466
 
467
  touch "/workspace/.provision_complete"
468
  log_success "配置標記文件已創建"