docs: 修复 spec 评审 7 个问题(test 命令、失败短路、变量校验等)

This commit is contained in:
deploy-bot
2026-06-02 21:43:57 +08:00
parent f6b3ba2d8c
commit 78e97f6fee
@@ -60,13 +60,21 @@ def enable_nginx_site(remote_conf: str, domain: str) -> bool:
### 5 步骤流程
| 步骤 | SSH 命令 | 失败处理 |
|---|---|---|
| 1. 诊断 | `ls -ld /etc/nginx/sites-enabled/{domain}.conf 2>&1; echo "---"; readlink -f /etc/nginx/sites-enabled/{domain}.conf 2>&1` | 仅诊断,不失败 |
| 2. 清理 | 若诊断结果是目录:`rm -rf <target>`<br>若是文件/链/不存在:跳过(rm -f 安全) | 失败时打印 stderr + 提示"权限可能不足" |
| 3. 建链 | `ln -snf {remote_conf} /etc/nginx/sites-enabled/{domain}.conf` | 失败时提示"scp_file 是否成功" |
| 4. 清默认 | `rm -f /etc/nginx/sites-enabled/default` | 失败时提示"default 文件被占用或权限不足" |
| 5. 验证 | `readlink /etc/nginx/sites-enabled/{domain}.conf && ls -la /etc/nginx/sites-enabled/` | 失败时打印实际值与期望值 |
| 步骤 | SSH 命令 | 失败处理 | 失败时是否继续 |
|---|---|---|---|
| 1. 诊断 | `test -e <target> && (test -L <target> && echo "symlink" \|\| (test -d <target> && echo "dir" \|\| echo "file")) \|\| echo "missing"` | 仅诊断,不失败 | — |
| 2. 清理 | `case 诊断结果 in symlink) unlink <target> ;; dir) rm -rf <target> ;; file) rm -f <target> ;; missing) ;; esac` | 失败时打印 stderr + 提示"权限可能不足" | **否**(清理失败则终止,不重建链) |
| 3. 建链 | `ln -snf {remote_conf} /etc/nginx/sites-enabled/{domain}.conf` | 失败时提示"scp_file 是否成功" | — |
| 4. 清默认 | `rm -f /etc/nginx/sites-enabled/default` | 失败时提示"default 文件被占用或权限不足" | — |
| 5. 验证 | `readlink /etc/nginx/sites-enabled/{domain}.conf && ls -la /etc/nginx/sites-enabled/` | 失败时打印实际值与期望值 | — |
**关键决策**
- **步骤 2 用 `test -e/-L/-d/-f` 替代 `ls -ld` 解析**shell 内置 test 比解析 `ls` 输出更可靠,跨 Unix 工具版本差异小
- **步骤 2 失败则短路终止**:清理失败时建链毫无意义(脏状态仍在),立即返回 False 让用户介入
- **有效 symlink 走 `unlink` 而非 `rm -f`**:与目录/文件区分对待,避免误删有效链接
- **缺失(missing)跳过清理**:直接进建链步骤,是最常见的健康场景
**超时设置**:每步独立调用 `ssh_command(cmd, timeout=30)`,与现有 `ssh_command()` 默认值一致。**不修改** `ssh_command()` / `run_ssh_args()` 底层,也不需要新增超时参数。30s 对单步 SSH 命令(不涉及大文件传输)足够;如未来出现网络慢问题,可在调用处单独覆盖(如 `ssh_command(cmd, timeout=60)`)。
### 集成位置
@@ -75,17 +83,43 @@ def enable_nginx_site(remote_conf: str, domain: str) -> bool:
- **第 250-256 行**:替换 `ln -snf ... && rm -f ...` 块为 `enable_nginx_site(remote_conf, DOMAIN)` 调用
- **第 232-266 行**`deploy_nginx` 函数)保持其他逻辑不变(scp_file 上传 conf、nginx -t、reload
- **新增函数** `enable_nginx_site` 放在 `deploy_nginx` 之前
- **实施方式**:5 步都是直接调用现有 `ssh_command()`(不修改底层),只是用 Python `if/elif/else` 在函数内串起来
### 变量安全校验
`enable_nginx_site(remote_conf, domain)` 函数入口处对 `domain` 做基本校验,防止变量污染导致误操作:
```python
import re
if not domain or not re.match(r'^[a-zA-Z0-9.-]+$', domain):
log_error(f"非法 domain 名称: {domain!r}")
return False
```
校验规则:
- 非空
- 仅包含字母、数字、点、连字符
- 不含 `/``*``;``&``|``$`、空格等 shell 特殊字符
`remote_conf` 来源固定(f-string 拼接 `f"/etc/nginx/sites-available/{DOMAIN}.conf"`),与 `domain` 一同校验。
### 错误信息改进
`enable_nginx_site` 内部用统一的 `log_error` 输出结构化信息:
`enable_nginx_site` 内部用统一的 `log_error` 输出结构化信息,**使用描述性名称而非"步骤 N"**
```
[ERROR] 启用站点失败 - 步骤 3 建链: Permission denied
[ERROR] 启用站点失败 - 建链步骤: Permission denied
[ERROR] 上下文: 目标 = /etc/nginx/sites-enabled/lifescript.happylifeos.com.conf
[ERROR] 提示: 确认 scp_file 是否成功上传了 sites-available 下的 conf 文件
```
各步骤使用的描述性名称:
- 诊断步骤
- 清理步骤
- 建链步骤
- 清默认步骤
- 验证步骤
替代当前的"命令执行超时 (30s)",便于快速定位卡在哪一步。
## 范围