From ace50650f642d62ff09b11c380be0e9c48e163d4 Mon Sep 17 00:00:00 2001 From: ClovertaTheTrilobita Date: Thu, 16 Oct 2025 17:31:03 +0000 Subject: [PATCH] =?UTF-8?q?feat(install):=20=E5=AE=8C=E5=96=84=E5=AE=89?= =?UTF-8?q?=E8=A3=85=E8=84=9A=E6=9C=AC=EF=BC=8C=E5=A4=9Adistro=E5=8F=AF?= =?UTF-8?q?=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- backend/config.yaml | 2 +- backend/flaskApp.py | 4 +- frontend/api.js | 2 +- install.sh | 322 +++++++++++++++++++++++++++++--------------- 5 files changed, 216 insertions(+), 117 deletions(-) diff --git a/.gitignore b/.gitignore index ba1b02a..81b71cf 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ __pycache__ .idea run models -backend/train/ \ No newline at end of file +backend/train/ +.bak diff --git a/backend/config.yaml b/backend/config.yaml index 9ce8471..19b138f 100644 --- a/backend/config.yaml +++ b/backend/config.yaml @@ -1,5 +1,5 @@ backend: - ip: 192.168.193.141 + ip: 10.10.25.240 port: 5000 model: diff --git a/backend/flaskApp.py b/backend/flaskApp.py index a7ce06c..bcf20d0 100644 --- a/backend/flaskApp.py +++ b/backend/flaskApp.py @@ -14,7 +14,7 @@ from flask import Flask, send_from_directory, request, jsonify from flask_cors import CORS from werkzeug.utils import secure_filename -from backend.cp_train import Cptrain +from cp_train import Cptrain from cp_run import Cprun app = Flask(__name__) @@ -236,4 +236,4 @@ def list_results(): st = get_status(task_id) if not st: return jsonify({"ok": True, "exists": False, "status": "not_found"}), 200 - return jsonify({"ok": True, "exists": True, **st}), 200 \ No newline at end of file + return jsonify({"ok": True, "exists": True, **st}), 200 diff --git a/frontend/api.js b/frontend/api.js index b84607a..a4df8f5 100644 --- a/frontend/api.js +++ b/frontend/api.js @@ -1,7 +1,7 @@ const config = { server: { protocol: 'http', - host: '192.168.193.141', + host: '10.10.25.240', port: 5000 } }; diff --git a/install.sh b/install.sh index 4edf0fe..e99779e 100755 --- a/install.sh +++ b/install.sh @@ -1,54 +1,57 @@ #!/usr/bin/env bash set -euo pipefail -GREEN='\033[32m'; RESET='\033[0m'; YELLOW='\033[33m'; RED='\033[41m' +GREEN='\033[32m' +RESET='\033[0m' +YELLOW='\033[33m' +RED='\033[31m' ask_yn() { # $1=提示语 $2=默认值 y|n local prompt="$1" local def="${2:-n}" - local show="[y/N]"; [ "$def" = "y" ] && show="[Y/n]" + local show="[y/N]" + [ "$def" = "y" ] && show="[Y/n]" while :; do - printf "%s %s " "$prompt" "$show" > /dev/tty - IFS= read -r ans < /dev/tty || return 1 + printf "%s %s " "$prompt" "$show" >/dev/tty + IFS= read -r ans /dev/tty ;; + [Yy] | [Yy][Ee][Ss]) return 0 ;; + [Nn] | [Nn][Oo]) return 1 ;; + *) echo "Please answer y or n." >/dev/tty ;; esac done } - #--- 小工具:取当前 backend.ip --- get_current_ip() { if command -v ip >/dev/null 2>&1; then - ip -4 route get 1.1.1.1 2>/dev/null \ - | awk '{for(i=1;i<=NF;i++) if($i=="src"){print $(i+1); exit}}' \ - | grep -E '^[0-9]+(\.[0-9]+){3}$' && return 0 + ip -4 route get 1.1.1.1 2>/dev/null | + awk '{for(i=1;i<=NF;i++) if($i=="src"){print $(i+1); exit}}' | + grep -E '^[0-9]+(\.[0-9]+){3}$' && return 0 # 次选:hostname -I - hostname -I 2>/dev/null \ - | awk '{print $1}' \ - | grep -E '^[0-9]+(\.[0-9]+){3}$' && return 0 + hostname -I 2>/dev/null | + awk '{print $1}' | + grep -E '^[0-9]+(\.[0-9]+){3}$' && return 0 fi # 2) macOS: ipconfig if [ "$(uname -s)" = "Darwin" ]; then for i in en0 en1 en2; do - ipconfig getifaddr "$i" 2>/dev/null \ - | grep -E '^[0-9]+(\.[0-9]+){3}$' && return 0 + ipconfig getifaddr "$i" 2>/dev/null | + grep -E '^[0-9]+(\.[0-9]+){3}$' && return 0 done fi # 3) 通用回退:ifconfig 解析 if command -v ifconfig >/dev/null 2>&1; then - ifconfig 2>/dev/null \ - | awk '/inet (addr:)?([0-9]+\.){3}[0-9]+/ { + ifconfig 2>/dev/null | + awk '/inet (addr:)?([0-9]+\.){3}[0-9]+/ { ip=$2; sub("addr:","",ip); if (ip!="127.0.0.1" && ip !~ /^127\./) {print ip; exit} - }' \ - | grep -E '^[0-9]+(\.[0-9]+){3}$' && return 0 + }' | + grep -E '^[0-9]+(\.[0-9]+){3}$' && return 0 fi # 4) 实在拿不到 @@ -57,20 +60,20 @@ get_current_ip() { #--- 简单 IPv4 校验(也可接受主机名;如只要 IPv4,保留第一个分支即可) --- is_valid_host() { - case "$1" in - # IPv4 快速匹配 + 数值检查 0–255 - ([0-9]*.[0-9]*.[0-9]*.[0-9]*) - IFS=. read -r a b c d <<<"$1" || return 1 - for o in "$a" "$b" "$c" "$d"; do - [[ "$o" =~ ^[0-9]{1,3}$ ]] || return 1 - (( o >= 0 && o <= 255 )) || return 1 - done - return 0 - ;; - # 主机名(允许 localhost、域名等) - ([A-Za-z0-9-]*([.][A-Za-z0-9-]+)*) return 0 ;; - (*) return 1 ;; - esac + local s=${1:-} + + # 先判 IPv4 形状 + if [[ $s =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then + IFS=. read -r a b c d <<<"$s" || return 1 + for o in "$a" "$b" "$c" "$d"; do + [[ $o =~ ^[0-9]{1,3}$ ]] || return 1 + ((o >= 0 && o <= 255)) || return 1 + done + return 0 + fi + + # 再判主机名(RFC1123 宽松版:标签 1-63,允许中划线但不能以 - 开头/结尾) + [[ $s =~ ^([A-Za-z0-9]([-A-Za-z0-9]{0,61}[A-Za-z0-9])?\.)*([A-Za-z0-9]([-A-Za-z0-9]{0,61}[A-Za-z0-9])?)$ ]] } update_frontend_ip() { @@ -85,7 +88,7 @@ update_frontend_ip() { } need_sudo() { - if [ "$EUID" -ne 0 ]; then echo "sudo" ; else echo "" ; fi + if [ "$EUID" -ne 0 ]; then echo "sudo"; else echo ""; fi } detect_distro() { @@ -98,63 +101,90 @@ detect_distro() { } install_debian() { + local package=$1 local SUDO=$(need_sudo) - $SUDO apt-get update -y - # python3-venv 是 Debian/Ubuntu 系 venv 必需包 - $SUDO apt-get install -y python3 python3-venv python3-pip build-essential + if [ "$package" = "python" ]; then + $SUDO apt-get update -y + # python3-venv 是 Debian/Ubuntu 系 venv 必需包 + $SUDO apt-get install -y python3 python3-venv python3-pip build-essential + elif [[ "$package" = "redis" ]]; then + $SUDO apt-get install -y redis-server redis-cli + $SUDO systemctl enable --now redis-server + fi + } install_arch() { + local package=$1 local SUDO=$(need_sudo) # Arch 的 python 包自带 venv 模块 - $SUDO pacman -Sy --needed --noconfirm python python-pip base-devel + if [[ "$package" = "python" ]]; then + $SUDO pacman -Sy --needed --noconfirm python python-pip base-devel + elif [[ "$package" = "redis" ]]; then + $SUDO pacman -Sy --needed --noconfirm valkey + $SUDO systemctl enable --now valkey + fi } install_rhel() { + local package=$1 local SUDO=$(need_sudo) # 优先 dnf;旧版用 yum。RHEL/CentOS/Fedora 的 python3 自带 venv if command -v dnf >/dev/null 2>&1; then - $SUDO dnf -y install python3 python3-pip - # 开发工具组(可选) + if [[ "$package" = "python" ]]; then + $SUDO dnf -y install python3 python3-pip + # 开发工具组(可选) + elif [[ "$package" = "redis" ]]; then + $SUDO dnf -y install redis + fi $SUDO dnf -y groupinstall "Development Tools" || true else - $SUDO yum -y install python3 python3-pip || true + if [[ "$package" = "python" ]]; then + $SUDO yum -y install python3 python3-pip || true + elif [[ "$package" = "redis" ]]; then + $SUDO yum install -y redis + fi $SUDO yum -y groupinstall "Development Tools" || true fi } install_python_venv() { - local info; info=$(detect_distro) - local id="${info%%|*}"; local like="${info#*|}" + local info + info=$(detect_distro) + local id="${info%%|*}" + local like="${info#*|}" echo "Detected: id=$id, like=$like" case "$id" in - arch|manjaro) - install_arch ;; - ubuntu|debian|linuxmint|pop|elementary|neon|kali|raspbian) - install_debian ;; - fedora|centos|rhel|rocky|almalinux|ol) - install_rhel ;; - *) - # 用 ID_LIKE 兜底 - if echo "$like" | grep -qi "debian"; then - install_debian - elif echo "$like" | grep -Eiq "rhel|fedora|centos"; then - install_rhel - elif echo "$like" | grep -qi "arch"; then - install_arch - else - echo "Unknown Linux distro: $id. Please install it manualy" - echo " Debian/Ubuntu: sudo apt-get install -y python3 python3-venv python3-pip" - echo " Arch/Manjaro: sudo pacman -S python python-pip" - echo " RHEL/CentOS: sudo dnf/yum install -y python3 python3-pip" - exit 1 - fi - ;; - esase + arch | manjaro) + install_arch + ;; + ubuntu | debian | linuxmint | pop | elementary | neon | kali | raspbian) + install_debian + ;; + fedora | centos | rhel | rocky | almalinux | ol) + install_rhel + ;; + *) + # 用 ID_LIKE 兜底 + if echo "$like" | grep -qi "debian"; then + install_debian "python" + elif echo "$like" | grep -Eiq "rhel|fedora|centos"; then + install_rhel "python" + elif echo "$like" | grep -qi "arch"; then + install_arch "python" + else + echo "Unknown Linux distro: $id. Please install it manualy" + echo " Debian/Ubuntu: sudo apt-get install -y python3 python3-venv python3-pip" + echo " Arch/Manjaro: sudo pacman -S python python-pip" + echo " RHEL/CentOS: sudo dnf/yum install -y python3 python3-pip" + exit 1 + fi + ;; + esac # 验证 venv 可用 - if python3 - <<'PY' + if python3 - <<'PY'; then import sys, subprocess, tempfile, os try: d = tempfile.mkdtemp(prefix="venv_test_") @@ -164,7 +194,6 @@ except Exception as e: print("ERR", e) raise PY - then echo "✅ python3 venv usable" else echo "❌ venv not usable Please check whether it's installed (Debian/Ubuntu: python3-venv)" >&2 @@ -172,11 +201,50 @@ PY fi } +install_redis() { + local info + info=$(detect_distro) + local id="${info%%|*}" + local like="${info#*|}" + echo "Detected: id=$id, like=$like" -if [ -n "$NO_COLOR" ]; then GREEN=''; RESET=''; fi + case "$id" in + arch | manjaro) + install_arch + ;; + ubuntu | debian | linuxmint | pop | elementary | neon | kali | raspbian) + install_debian + ;; + fedora | centos | rhel | rocky | almalinux | ol) + install_rhel + ;; + *) + # 用 ID_LIKE 兜底 + if echo "$like" | grep -qi "debian"; then + install_debian "redis" + elif echo "$like" | grep -Eiq "rhel|fedora|centos"; then + install_rhel "redis" + elif echo "$like" | grep -qi "arch"; then + install_arch "redis" + else + echo "Unknown Linux distro: $id. Please install it manualy" + echo " Debian/Ubuntu: sudo apt-get install -y redis-server redis-cli" + echo " Arch/Manjaro: sudo pacman -S valkey" + echo " RHEL/CentOS: sudo dnf/yum install -y redis" + exit 1 + fi + ;; + esac + +} + +#if [ -n "$NO_COLOR" ]; then +# GREEN='' +# RESET='' +#fi root=$(git rev-parse --show-toplevel 2>/dev/null) || root="" -if [ -n "$root" ]; then +if [ -n "$root" ]; then echo -e "${GREEN}==>${RESET} ✅Inside a git repo, root: ${root}" echo -e "${GREEN}==>${RESET} Checking for update..." git pull origin master @@ -185,23 +253,36 @@ else if ask_yn "Do you wish to clone it from github?" y; then echo "${GREEN}==>${RESET} Cloning from remote..." git clone https://github.com/ClovertaTheTrilobita/cellpose-web.git - fi -fi -if ! cd cellpose-web; then - echo "${RED}==>${RESET} directory 'cellpose-web' not found or inaccessible, did git clone run successfully?" >&2 - exit 1 + if ! cd cellpose-web; then + echo -e "${RED}==>${RESET} directory 'cellpose-web' not found or inaccessible, did git clone run successfully?" >&2 + exit 1 + fi + fi fi root=$(pwd) echo -e "${GREEN}==>${RESET} STARTING DEPLOY..." +if command -v valkey-server >/dev/null 2>&1 || command -v redis-cli >/dev/null 2>&1 || command -v redis-server >/dev/null 2>&1; then + # 打印版本(有哪个用哪个) + ver="$(redis-cli --version 2>/dev/null || redis-server --version 2>/dev/null)" + echo -e "${GREEN}==>${RESET} Redis installed: $ver" +else + echo -e "${YELLOW}==>${RESET} Redis not detected." + if ask_yn "Do you like to install redis on your machine?" y; then + install_redis + fi +fi + FILE="${root}/backend/config.yaml" DEFAULT_IP="$(get_current_ip || true)" echo -e "${GREEN}==>${RESET} Enter IP address of your machine (empty: default ${DEFAULT_IP}):" +prompt=${prompt:-"Enter server IP/host"} # 先初始化 prompt +curr_ip=${curr_ip:-} [ -n "${curr_ip:-}" ] && prompt="$prompt (current: $curr_ip)" -printf "%s: " "$prompt" > /dev/tty -IFS= read -r NEW_IP < /dev/tty +printf "%s: " "$prompt" >/dev/tty +IFS= read -r NEW_IP /dev/null 2>&1; then NEW_IP_ENV="$NEW_IP" yq -i '.backend.ip = strenv(NEW_IP_ENV)' "$FILE" else awk -v newip="$NEW_IP" ' - BEGIN{in=0; base=-1; done=0} - /^[[:space:]]*backend:[[:space:]]*$/ {in=1; base=match($0,/[^ ]/)-1; print; next} + BEGIN { inblk=0; base=-1; done=0 } + /^[[:space:]]*backend:[[:space:]]*$/ { inblk=1; base=indent($0); print; next } { - if(in && !done){ - ind=match($0,/[^ ]/)-1 - if(ind<=base){in=0} - else if($0 ~ /^[[:space:]]*ip:[[:space:]]*/){ - match($0,/^[[:space:]]*/); sp=substr($0,1,RLENGTH) + if (inblk && !done) { + ind = indent($0) + if (ind <= base) { inblk=0 } + else if ($0 ~ /^[[:space:]]*ip:[[:space:]]*/) { + match($0, /^[[:space:]]*/); sp = substr($0, 1, RLENGTH) print sp "ip: " newip done=1; next } } print } - ' "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE" + function indent(s, n) { + match(s, /^[[:space:]]*/) + return RLENGTH + } + ' "$FILE" >"$FILE.tmp" && mv "$FILE.tmp" "$FILE" fi echo -e "${GREEN}==>${RESET} Updated backend.ip -> $NEW_IP in $FILE" -update_frontend_ip $NEW_IP +update_frontend_ip $NEW_IP $root echo -e "${GREEN}==>${RESET} Update host -> $NEW_IP in frontend/api.js" -if ! conda; then +if command -v conda >/dev/null 2>&1; then + echo "Conda already installed: $(conda --version)" + CONDA_EXE="${CONDA_EXE:-$(command -v conda)}" + CONDA_BASE="$("$CONDA_EXE" info --base)" + eval "$("$CONDA_EXE" shell.bash hook)" + conda create -n cpweb python=3.12 + conda activate cpweb +else echo -e "${YELLOW}==>${RESET} Conda enviroment NOT FOUND" echo "We highly recommend you to use Conda to manage python enviroments" if ask_yn "Do you wish to install miniconda?" y; then - wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh - bash miniconda.sh -b -p $HOME/miniconda3 - rm miniconda.sh - eval "$($HOME/miniconda3/bin/conda shell.bash hook)" + wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh + bash miniconda.sh -b -p $HOME/miniconda3 + rm miniconda.sh + eval "$($HOME/miniconda3/bin/conda shell.bash hook)" conda init + conda create -n cpweb python=3.12 || true + conda activate cpweb else echo -e "${GREEN}==>${RESET} Creating Python venv..." - if [ "$(uname -s)" = "Darwin" ]; then - if ! brew install python; them - echo -e"${RED}==>${RESET} You are using macOS/BSD with no homebrew, we don't recommend you to use system python on macOS, aborting..." - exit 1 - fi - else - install_python_venv "$@" - python3 -m venv .venv - . .venv/bin/activate - python -V - echo -e "${GREEN}==>${RESET} Successfully created venv" - fi + if [ "$(uname -s)" = "Darwin" ]; then + if ! command -v brew >/dev/null 2>&1; then + echo -e "${RED}==>${RESET} You are using macOS/BSD with no homebrew, we don't recommend you to use system python on macOS, aborting..." + exit 1 + fi + if ! brew install python >/dev/null 2>&1; then + echo -e "${RED}==>${RESET} Failed to install Python via Homebrew.\n" + exit 1 + fi + else + install_python_venv "$@" + python3 -m venv .venv + . .venv/bin/activate + python -V + echo -e "${GREEN}==>${RESET} Successfully created venv" + fi fi -else - conda create -n cpweb python=3.12 || true - conda activate cpweb fi if ! cd "${root}/backend"; then @@ -288,7 +383,12 @@ fi echo -e "${GREEN}==>${RESET} Preparing to install dependencies..." if ask_yn "Do you want to install it now?" y; then - pip install -r requirements.txt + if ! cd "${root}"; then + echo -e "${RED}==>${RESET} unable to access ${root}, did you edit project structre?" + exit 1 + fi + + python -m pip install -r requirements.txt else echo -e "${YELLOW}==>${RESET} Operation canceled, exiting..." exit 1 @@ -296,7 +396,5 @@ fi echo -e "${GREEN}==>${RESET} Deployment successfull" if ask_yn "Do you wish to start cellpose server now?" y; then - python main.py + python ${root}/backend/main.py fi - -