cellpose-web/install.sh

302 lines
8.7 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
set -euo pipefail
GREEN='\033[32m'; RESET='\033[0m'; YELLOW='\033[33m'; RED='\033[41m'
ask_yn() {
# $1=提示语 $2=默认值 y|n
local prompt="$1"
local def="${2:-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
[ -z "$ans" ] && ans="$def"
case "$ans" in
[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
# 次选hostname -I
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
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]+/ {
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
fi
# 4) 实在拿不到
return 1
}
#--- 简单 IPv4 校验(也可接受主机名;如只要 IPv4保留第一个分支即可 ---
is_valid_host() {
case "$1" in
# IPv4 快速匹配 + 数值检查 0255
([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
}
update_frontend_ip() {
local IP=$1
local ROOT_DIR=$2
if [ "$(uname -s)" = "Darwin" ]; then
sed -E -i '' "s/(host[[:space:]]*:[[:space:]]*['\"])([^'\"]*)(['\"])/\1$NEW_IP\3/" frontend/api.js
else
sed -E -i.bak "s/(host[[:space:]]*:[[:space:]]*['\"])([^'\"]*)(['\"])/\1$NEW_IP\3/" frontend/api.js
fi
}
need_sudo() {
if [ "$EUID" -ne 0 ]; then echo "sudo" ; else echo "" ; fi
}
detect_distro() {
if [ -r /etc/os-release ]; then
. /etc/os-release
echo "${ID:-unknown}|${ID_LIKE:-}"
else
echo "unknown|"
fi
}
install_debian() {
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
}
install_arch() {
local SUDO=$(need_sudo)
# Arch 的 python 包自带 venv 模块
$SUDO pacman -Sy --needed --noconfirm python python-pip base-devel
}
install_rhel() {
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
# 开发工具组(可选)
$SUDO dnf -y groupinstall "Development Tools" || true
else
$SUDO yum -y install python3 python3-pip || true
$SUDO yum -y groupinstall "Development Tools" || true
fi
}
install_python_venv() {
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
# 验证 venv 可用
if python3 - <<'PY'
import sys, subprocess, tempfile, os
try:
d = tempfile.mkdtemp(prefix="venv_test_")
subprocess.check_call([sys.executable, "-m", "venv", os.path.join(d, "v")], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
print("OK")
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
exit 1
fi
}
if [ -n "$NO_COLOR" ]; then GREEN=''; RESET=''; fi
root=$(git rev-parse --show-toplevel 2>/dev/null) || root=""
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
else
echo -e "${YELLOW}==>${RESET} Repo enviroment not found"
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
fi
root=$(pwd)
echo -e "${GREEN}==>${RESET} STARTING DEPLOY..."
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}):"
[ -n "${curr_ip:-}" ] && prompt="$prompt (current: $curr_ip)"
printf "%s: " "$prompt" > /dev/tty
IFS= read -r NEW_IP < /dev/tty
# 默认回车使用探测到的 IP
if [ -z "${NEW_IP}" ]; then
if [ -n "${DEFAULT_IP:-}" ]; then
NEW_IP="$DEFAULT_IP"
echo -e "${GREEN}==>${RESET} Using detected IP: $NEW_IP"
else
echo -e "${RED}==>${RESET} No input and no IP detected. Aborted." >&2
exit 1
fi
fi
if ! is_valid_host "$NEW_IP"; then
echo -e "${RED}==>${RESET} Invalid IP/hostname: $NEW_IP" >&2
if ask_yn "Do you wish to use default ip (${DEFAULT_IP})?" y; then
echo -e "${GREEN}==>${RESET} Using detected IP: $NEW_IP"
else
exit 1
fi
fi
cp -a -- "$FILE" "$FILE.bak.$(date +%Y%m%d%H%M%S)"
if command -v yq >/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}
{
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)
print sp "ip: " newip
done=1; next
}
}
print
}
' "$FILE" > "$FILE.tmp" && mv "$FILE.tmp" "$FILE"
fi
echo -e "${GREEN}==>${RESET} Updated backend.ip -> $NEW_IP in $FILE"
update_frontend_ip $NEW_IP
echo -e "${GREEN}==>${RESET} Update host -> $NEW_IP in frontend/api.js"
if ! conda; then
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)"
conda init
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
fi
else
conda create -n cpweb python=3.12 || true
conda activate cpweb
fi
if ! cd "${root}/backend"; then
echo -e "${RED}==>${RESET} dir backend/ missing, did you edit project structre?"
exit 1
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
else
echo -e "${YELLOW}==>${RESET} Operation canceled, exiting..."
exit 1
fi
echo -e "${GREEN}==>${RESET} Deployment successfull"
if ask_yn "Do you wish to start cellpose server now?" y; then
python main.py
fi