Files
Nexus/docs/audit/2026-06-04-encoding-review-ubuntu-phase1.md
T
2026-07-08 22:31:31 +08:00

132 lines
4.6 KiB
Markdown
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.
# 编码 / 换行审查 — Ubuntu 工作区(阶段 1)
| 项 | 内容 |
|----|------|
| 日期 | 2026-06-04 |
| 范围 | Git 索引 vs 工作区、运行时 UTF-8/EOL、Windows 遗留路径 |
| 前置 | `docs/audit/2026-06-02-windows-ubuntu-encoding-deep-dive.md` |
---
## 阶段 1 结论(摘要)
| 维度 | Git 索引(部署真相) | 本机工作区(tar/检出) |
|------|----------------------|----------------------|
| `check_text_eol.py` | **PASS**206 路径无 CR | — |
| `check_shell_eol.sh` | **PASS** | — |
| `check_worktree_eol.py` | — | **FAIL**(约 171 个跟踪文件磁盘含 `\r` |
| 运行时写 `.env` | `install.py` / `sync_mysql_mcp_env` 已用 `text_io` | — |
| 新脚本 `proxy-env.sh` 等 | 未入库前曾 **CRLF** | 已 `sed` 去 CR |
**核心区分**Ubuntu 生产以 **`git pull` 的索引 blob** 为准;离线 tar 解压到本机后,工作区可能是 CRLF,会导致 `source *.sh``未找到命令`(行尾 `\r`)。
---
## 1. 已有防护(保持)
| 组件 | 路径 |
|------|------|
| SSOT | `server/utils/text_io.py` |
| 索引门控 | `scripts/check_text_eol.py` |
| Shell 门控 | `deploy/check_shell_eol.sh` |
| 编辑器 | `.editorconfig``charset=utf-8`, `eol=lf` |
| Git | `.gitattributes``*.py/sh/vue/ts` = `eol=lf` |
| 部署 Pre-flight | `deploy/pre_deploy_check.sh` 调用上述门控 |
---
## 2. 本轮发现(按严重度)
### P1 — 工作区 CRLF vs 索引 LF
- **现象**`grep -l $'\r'``server/**/*.py` 等约 **171** 个已跟踪文件命中;`file scripts/proxy-env.sh` 显示 `CRLF line terminators`
- **影响**bash `source scripts/proxy-env.sh` 出现 `:未找到命令`;不影响已从 Git 拉取的 Ubuntu 服务器(索引为 LF)。
- **修复**
```bash
git config core.autocrlf false
bash scripts/normalize_worktree_lf.sh
python3 scripts/check_worktree_eol.py
```
### P2 — `docker/sync_root_env.py` 未走 `text_io`(已修)
- **问题**`read_text`/`write_text` 未归一化 CRLFWindows 生成的 `docker/.env` 可能把 `\r` 带进 `NEXUS_*`。
- **修复**:改用 `read_utf8_lf` / `write_utf8_lf`。
### P2 — `linux_mcp_mysql.sh` 读 `.env` 未去 `\r`(已修)
- **问题**`export MYSQL_PASSWORD=xxx\r` 导致 MCP 连库失败。
- **修复**`line="${line%$'\r'}"`。
### P3 — `web/agent/agent.py` 读 `/etc/os-release` 无 encoding(已修)
- **修复**`read_text(encoding="utf-8")`Linux 标准 UTF-8)。
### 合理设计(非缺陷)
| 位置 | 说明 |
|------|------|
| `servers.py` CSV 导入 | `utf-8-sig` → 失败则 `gbk`(中文 Excel |
| `sync_v2.read_file` | `detect_text_eol` + 前端 `stripCr` / `serializeContent` |
| `sync_v2.write_file` | `content.encode("utf-8")` 字节写入远程 |
| `posix_paths.py` | 拒绝远程路径中的 `\` |
| `auth_jwt` / `main` | HTTP header `latin-1`RFC 7230 |
### 文档 / 配置中的 Windows 路径(仅文档,不影响运行)
- `docs/handoff-*.md``mysql-mcp-setup.md` 仍含 `C:\Users\...` — 阶段 2 可改为 `$NEXUS_ROOT` / `~/Nexus`
---
## 3. 远程文件链(复查)
```
read-file: SSH cat → str → detect_text_eol → JSON { content, eol }
write-file: JSON → .encode("utf-8") → SFTP/tee(不经本机换行转换)
```
经典 Mac `\r` 在 API 层标为 `eol: LF`;前端 `stripCr` 统一编辑为 LF。
---
## 4. 阶段 2(已完成 — 见 phase2 文档)
- [x] `frontend/` 工作区 LF 清零(`check_worktree_eol` OK
- [x] `.cursor/rules/*.mdc` 归一化 + 门控扩展
- [x] `web/agent/agent.py` I/O 审查
- [x] `mysql-mcp-setup.md` Linux/WSL 路径
- [ ] `vue-tsc` 3 处类型错误(非编码)
- [ ] 历史 handoff 文档 Windows 路径(可选)
详见:`docs/audit/2026-06-04-encoding-review-ubuntu-phase2.md`
---
## 5. Closure
| H | 判定 | 依据 |
|---|------|------|
| H-index-LF | PASS | `check_text_eol` + `check_shell_eol` |
| H-worktree-CRLF | FIXED | `normalize_worktree_lf.sh` + `check_worktree_eol` OK |
| H-sync-root-env | FIXED | `docker/sync_root_env.py``text_io` |
| H-mcp-sh-env | FIXED | `linux_mcp_mysql.sh` strip `\r` |
| H-agent-os-release | FIXED | `encoding=utf-8` |
## DoD(阶段 1
- [x] 跑通双门控 + 工作区扫描
- [x] 修复本轮 3 处代码
- [x] 新增 `check_worktree_eol.py` / `normalize_worktree_lf.sh`
- [x] 审计记录与 changelog
## 验证
```bash
python3 scripts/check_text_eol.py
bash deploy/check_shell_eol.sh
bash scripts/normalize_worktree_lf.sh
python3 scripts/check_worktree_eol.py
pytest tests/test_text_io.py -q
python3 docker/sync_root_env.py
```