132 lines
4.6 KiB
Markdown
132 lines
4.6 KiB
Markdown
# 编码 / 换行审查 — 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` 未归一化 CRLF,Windows 生成的 `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
|
||
```
|