diff --git a/docs/18_domainCheck_CentOS9一键复制部署与更新文档.md b/docs/18_domainCheck_CentOS9一键复制部署与更新文档.md index 7d94c9a..7088a83 100644 --- a/docs/18_domainCheck_CentOS9一键复制部署与更新文档.md +++ b/docs/18_domainCheck_CentOS9一键复制部署与更新文档.md @@ -190,6 +190,28 @@ ln -sfn /www/wwwroot/getDomain/domainCheck /opt/domaincheck/domainCheck - 建议统一到 `Node 20` - 生产构建时只要保证执行构建命令前已经 `nvm use 20` +### 6.1 `nvm` 安装命令 + +如果机器还没有安装 `nvm`,先执行: + +```bash +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash + +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" +[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" + +nvm -v +nvm install 20 +nvm use 20 +``` + +补充说明: + +- 国外机器如果要构建前端,必须先确保 `nvm` 可用 +- 一键部署脚本会调用 `nvm install 20` 和 `nvm use 20` +- 所以脚本执行用户的 `HOME` 下必须已经安装好 `nvm` + ### 7. 你实际应该怎么选 - 如果国外主控机已经是宝塔机: @@ -232,6 +254,75 @@ python3.11 --version Python 3.11.x ``` +### 8.1 Linux 依赖安装特别说明 + +`domainCheck/requirements.txt` 是从桌面版沿用过来的,里面包含 Windows 专用依赖,例如: + +- `pywin32` +- `pywin32-ctypes` +- `twisted-iocpsupport` +- `win32-setctime` + +这些包在 Linux 上不能直接安装。 + +现在的 3 个一键部署脚本已经内置了兼容处理: + +- 会自动读取 `domainCheck/requirements.txt` +- 自动生成 `requirements.linux.txt` +- 自动过滤掉 Windows-only 依赖 +- 然后再执行 Linux 环境安装 + +所以现在在 Linux 上看到这类报错时,正确处理方式不是手工删仓库依赖,而是: + +1. 先 `git pull` +2. 确认脚本已经更新到最新版本 +3. 重新执行一键部署脚本 + +如果你是手工部署,不走一键脚本,那就不要直接跑: + +```bash +pip install -r requirements.txt +``` + +而应该改成: + +```bash +cd /opt/domaincheck/domainCheck +python3.11 - <<'PY' +from pathlib import Path + +source = Path("requirements.txt") +target = Path("requirements.linux.txt") +raw = source.read_bytes() +for encoding in ("utf-8", "utf-16", "utf-16-le", "utf-16-be", "gbk"): + try: + text = raw.decode(encoding) + break + except UnicodeDecodeError: + continue +else: + raise SystemExit("无法解析 requirements.txt 编码") + +skip_prefixes = ( + "pywin32==", + "pywin32-ctypes==", + "twisted-iocpsupport==", + "win32-setctime==", +) +lines = [] +for line in text.splitlines(): + normalized = line.strip().lstrip("\ufeff") + if normalized.lower().startswith(skip_prefixes): + continue + lines.append(normalized) + +target.write_text("\n".join(lines) + "\n", encoding="utf-8") +PY + +source .venv/bin/activate +pip install -r requirements.linux.txt +``` + ## 四、最短复制块 这一节给你三段最短命令。 @@ -268,6 +359,8 @@ bash /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_overseas_quic - 这条脚本不会执行 `git fetch` - 这条脚本不会执行 `git pull` - 你要先自己把 `/www/wwwroot/getDomain` 更新到目标版本,再跑脚本 +- 这条脚本会自动过滤 Windows-only Python 依赖 +- 这条脚本结束时会自动执行:`chown -R www:www /www/wwwroot/getDomain` ```bash cd /www/wwwroot/getDomain @@ -370,6 +463,8 @@ bash /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_mainland_cont - 这条脚本不会执行 `git fetch` - 这条脚本不会执行 `git pull` - 你要先自己把 `/www/wwwroot/getDomain` 更新到目标版本,再跑脚本 +- 这条脚本会自动过滤 Windows-only Python 依赖 +- 这条脚本结束时会自动执行:`chown -R www:www /www/wwwroot/getDomain` ```bash cd /www/wwwroot/getDomain @@ -468,6 +563,8 @@ bash /www/wwwroot/getDomain/domain-api/deploy/multi-region/install_mainland_work - 这条脚本不会执行 `git fetch` - 这条脚本不会执行 `git pull` - 你要先自己把 `/www/wwwroot/getDomain` 更新到目标版本,再跑脚本 +- 这条脚本会自动过滤 Windows-only Python 依赖 +- 这条脚本结束时会自动执行:`chown -R www:www /www/wwwroot/getDomain` ```bash cd /www/wwwroot/getDomain @@ -573,7 +670,37 @@ cd /opt/domaincheck/domainCheck python3.11 -m venv .venv source .venv/bin/activate pip install --upgrade pip -pip install -r requirements.txt +python3.11 - <<'PY' +from pathlib import Path + +source = Path("requirements.txt") +target = Path("requirements.linux.txt") +raw = source.read_bytes() +for encoding in ("utf-8", "utf-16", "utf-16-le", "utf-16-be", "gbk"): + try: + text = raw.decode(encoding) + break + except UnicodeDecodeError: + continue +else: + raise SystemExit("无法解析 requirements.txt 编码") + +skip_prefixes = ( + "pywin32==", + "pywin32-ctypes==", + "twisted-iocpsupport==", + "win32-setctime==", +) +lines = [] +for line in text.splitlines(): + normalized = line.strip().lstrip("\ufeff") + if normalized.lower().startswith(skip_prefixes): + continue + lines.append(normalized) + +target.write_text("\n".join(lines) + "\n", encoding="utf-8") +PY +pip install -r requirements.linux.txt cd /opt/domaincheck/domain-api /opt/domaincheck/domainCheck/.venv/bin/pip install fastapi uvicorn pydantic-settings psycopg2-binary redis openpyxl python-multipart @@ -665,7 +792,19 @@ EOF ### 7. 用 `nvm` 构建前端 -如果你平时就是 `nvm`,建议直接固定: +如果这台机器还没装 `nvm`,先执行: + +```bash +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash + +export NVM_DIR="$HOME/.nvm" +[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" +[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" + +nvm -v +``` + +然后固定使用: ```bash export NVM_DIR="$HOME/.nvm" @@ -712,6 +851,7 @@ touch /opt/domaincheck/domainCheck/detect_worker.log chown -R www:www /opt/domaincheck/domain-api/runtime chown www:www /opt/domaincheck/domainCheck/detect_worker.log chmod 664 /opt/domaincheck/domainCheck/detect_worker.log +chown -R www:www /www/wwwroot/getDomain ``` ### 11. 启动国外服务 @@ -989,6 +1129,7 @@ git pull --ff-only origin main ```bash export NVM_DIR="$HOME/.nvm" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" +nvm install 20 nvm use 20 cd /opt/domaincheck/domain-web @@ -1013,6 +1154,12 @@ systemctl restart domaincheck-sync-agent systemctl restart domaincheck-worker ``` +补充说明: + +- 一键部署脚本更新后,会在脚本末尾自动执行一次: + - `chown -R www:www /www/wwwroot/getDomain` +- 如果你是完全手工更新,也建议补执行一次,避免后续 `www` 用户 `git pull` 或宝塔读写再次撞权限 + ## 十、最终联调检查 在国外机器执行: diff --git a/domain-api/deploy/multi-region/install_mainland_controller_quick.sh b/domain-api/deploy/multi-region/install_mainland_controller_quick.sh index ed94bf2..eba5211 100755 --- a/domain-api/deploy/multi-region/install_mainland_controller_quick.sh +++ b/domain-api/deploy/multi-region/install_mainland_controller_quick.sh @@ -52,7 +52,37 @@ cd "${DOMAINCHECK_DIR}" python3.11 -m venv .venv || true source .venv/bin/activate pip install --upgrade pip -pip install -r requirements.txt +python3.11 - <<'PY' +from pathlib import Path + +source = Path("requirements.txt") +target = Path("requirements.linux.txt") +raw = source.read_bytes() +for encoding in ("utf-8", "utf-16", "utf-16-le", "utf-16-be", "gbk"): + try: + text = raw.decode(encoding) + break + except UnicodeDecodeError: + continue +else: + raise SystemExit("无法解析 requirements.txt 编码") + +skip_prefixes = ( + "pywin32==", + "pywin32-ctypes==", + "twisted-iocpsupport==", + "win32-setctime==", +) +lines = [] +for line in text.splitlines(): + normalized = line.strip().lstrip("\ufeff") + if normalized.lower().startswith(skip_prefixes): + continue + lines.append(normalized) + +target.write_text("\n".join(lines) + "\n", encoding="utf-8") +PY +pip install -r requirements.linux.txt "${DOMAINCHECK_DIR}/.venv/bin/pip" install fastapi uvicorn pydantic-settings psycopg2-binary redis openpyxl python-multipart cat >"${DOMAINCHECK_DIR}/.env" <"${DOMAINCHECK_DIR}/.env" <"${DOMAINCHECK_DIR}/.env" <