frpsctl 0.3.2__tar.gz → 0.3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {frpsctl-0.3.2 → frpsctl-0.3.3}/.github/workflows/release.yml +1 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/CHANGELOG.md +50 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/PKG-INFO +37 -12
- {frpsctl-0.3.2 → frpsctl-0.3.3}/README.md +36 -11
- {frpsctl-0.3.2 → frpsctl-0.3.3}/frpsctl-/350/256/276/350/256/241/346/226/271/346/241/210.md +129 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/__init__.py +1 -1
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/commands/plugin.py +260 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/commands/web.py +353 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/runtime.py +44 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/doctor.py +74 -0
- frpsctl-0.3.3/src/frpsctl/core/serve_runtime.py +495 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/uninstall.py +44 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/errors.py +26 -2
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/web/static/index.html +605 -75
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/snapshots/cli_commands.json +392 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_cli.py +300 -7
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_plugin.py +9 -3
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_units.py +533 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_web_frontend.py +25 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/.github/workflows/ci.yml +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/.gitignore +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/LICENSE +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/NOTICE +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/install.sh +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/pyproject.toml +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/__main__.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/capabilities.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/__init__.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/app.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/commands/__init__.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/commands/config.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/commands/install.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/commands/lifecycle.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/commands/observe.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/commands/service.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/context.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/cli/ui.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/__init__.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/admin.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/auditlog.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/config.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/diagnostics.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/health.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/healthcheck.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/httpserver.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/instance.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/lifecycle.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/lock.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/logs.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/platform.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/release.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/schema.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/systemd.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/transaction.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/version.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/core/web_audit.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/docs.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/env.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/plugin/__init__.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/plugin/audit.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/plugin/engine.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/plugin/policy.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/plugin/quota.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/plugin/server.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/plugin/types.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/py.typed +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/report.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/web/__init__.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/web/api.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/web/auth.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/web/cache.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/web/metrics.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/src/frpsctl/web/server.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/__init__.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/conftest.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/fake_frps.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/faults.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_contract_snapshot.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_docs.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_facts.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_faults.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_installer.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_integration.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_report.py +0 -0
- {frpsctl-0.3.2 → frpsctl-0.3.3}/tests/test_web.py +0 -0
|
@@ -3,6 +3,56 @@
|
|
|
3
3
|
格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),
|
|
4
4
|
版本号遵循[语义化版本](https://semver.org/lang/zh-CN/)。
|
|
5
5
|
|
|
6
|
+
## [0.3.3] - 2026-09-20
|
|
7
|
+
|
|
8
|
+
**后台服务与 Web 体验(systemd 之外的第二种托管形态 + 管理台视觉/交互大改)**。
|
|
9
|
+
Web 管理台与插件服务新增 `start|stop|restart|status`(direct 后台,与 systemd
|
|
10
|
+
双向互斥);管理台前端重做设计系统(极光/玻璃/霓虹)、图表 2.0 与交互升级。
|
|
11
|
+
新增 39 条测试(828 → 869;非契约 798 → 839),契约快照 +8 命令。
|
|
12
|
+
|
|
13
|
+
### 新增
|
|
14
|
+
|
|
15
|
+
- **`web start|stop|restart|status` / `plugin start|stop|restart|status`**:
|
|
16
|
+
非 systemd 环境的后台托管(子进程就是 `serve`,与 `ExecStart` 同构)——
|
|
17
|
+
状态与启动参数落 `<实例>/web|plugin-state.json`(0600),日志落
|
|
18
|
+
`<实例>/web|plugin.log`(8 MiB 轮转),停止走 SIGTERM → 等待 → SIGKILL。
|
|
19
|
+
`restart` 复用上次参数(可覆盖);`status` 统一显示 `systemd / direct /
|
|
20
|
+
none` 三种归属。
|
|
21
|
+
- **后台进程的三重校验**(`core/serve_runtime.py`):pid 存活 + 启动时刻 +
|
|
22
|
+
命令行含 `serve` 标记;状态文件损坏/陈旧/指向外人一律拒绝而不是猜测
|
|
23
|
+
(ADR-7 同一纪律)。
|
|
24
|
+
- **口令衔接**:`web start` 未给口令来源时默认用/生成实例内 `web-password`
|
|
25
|
+
(与 `web password set|show` 同一文件);`--password` 的值也先写文件——
|
|
26
|
+
后台模式口令可读回,且明文不出现在进程命令行里。
|
|
27
|
+
- **互斥与孤儿防护**:`web/plugin start` 对 active 的 systemd unit 拒绝
|
|
28
|
+
(反之 `service install|start|restart` 对存活的 direct 进程同样拒绝);
|
|
29
|
+
`uninstall` 预检新增 direct 服务(运行中拒绝,`--force` 先停再卸),
|
|
30
|
+
`doctor` 报告 direct 服务状态(运行中 INFO / 状态损坏 WARN / 身份不符 ERROR)。
|
|
31
|
+
- **管理台 UI 重做**:极光渐变背景 + 玻璃卡片 + 渐变强调色 + 状态呼吸灯 +
|
|
32
|
+
渐变指标条(首次滚动);骨架屏与空态;自绘确认弹层(替代原生 confirm,
|
|
33
|
+
支持 Enter/Esc);toast 图标与进度条;登录页重做;主题切换平滑过渡。
|
|
34
|
+
- **图表 2.0**:7 天柱状与实时曲线改渐变(CSS 变量驱动,主题即时生效);
|
|
35
|
+
实时曲线平滑(Catmull-Rom→贝塞尔)并加面积填充;两者都有悬浮十字线 +
|
|
36
|
+
自绘 SVG 浮动提示(不引入任何内联 style,CSP 不变)。
|
|
37
|
+
- **交互**:快捷键(`g d/g c/g a` 导航、`r` 刷新、`/` 聚焦过滤、`Esc` 关闭)、
|
|
38
|
+
客户端/代理/审计表格本地过滤、客户端/代理点表头排序、双击复制名称、
|
|
39
|
+
日志 ERROR/WARN 着色与一键复制、`prefers-reduced-motion` 全动画关闭。
|
|
40
|
+
|
|
41
|
+
### 变更
|
|
42
|
+
|
|
43
|
+
- 仪表盘"概览"卡并入顶部"实时概览"指标条(同一批数字不再重复展示)。
|
|
44
|
+
- npm/构建链保持零引入:仍是单文件前端(CSP nonce、无外部资源、无内联
|
|
45
|
+
style);前端守卫新增组件样式/无障碍/原生弹窗禁用 3 条断言。
|
|
46
|
+
|
|
47
|
+
### 测试
|
|
48
|
+
|
|
49
|
+
- 新增 39 条(828 → 869;非契约 798 → 839):serve_runtime 真进程全边界
|
|
50
|
+
(启动/停止/陈旧/外人/损坏/早退/端口未就绪/SIGKILL 兜底/日志轮转)、
|
|
51
|
+
**真链路 e2e**(`python -m frpsctl web serve` → HTTP 200 → stop;
|
|
52
|
+
`plugin serve` → Login 裁决 → stop 后审计刷盘)、CLI 后台命令接线与 JSON、
|
|
53
|
+
systemd↔direct 互斥(web/plugin 双向)、uninstall 孤儿防护、doctor
|
|
54
|
+
进程与端口一致性发现、前端守卫扩展 3 条。
|
|
55
|
+
|
|
6
56
|
## [0.3.2] - 2026-09-20
|
|
7
57
|
|
|
8
58
|
**systemd 全用户支持(任何账户都可以作服务用户)**。`frps` 不再是写死的默认:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: frpsctl
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
4
4
|
Summary: 把 frp 服务端(frps)包装成命令行工具:配置翻译器 + 进程保镖 + 状态聚合器
|
|
5
5
|
Project-URL: Homepage, https://github.com/ThzxxArt/frpsctl
|
|
6
6
|
Project-URL: Repository, https://github.com/ThzxxArt/frpsctl
|
|
@@ -110,8 +110,8 @@ CLI 负责精确控制与脚本化,Web 管理台负责可视化与日常操作
|
|
|
110
110
|
| 观测与运维 | `clients` / `proxies` / `traffic` / `instances` / `doctor` / `prune` / `capabilities`(能力清单) |
|
|
111
111
|
| 卸载 | `uninstall`(`--all` / `--keep-data` / `--keep-bin` / `--force`) |
|
|
112
112
|
| systemd 集成 | `service install` / `uninstall` / `status` / `logs` |
|
|
113
|
-
| 服务端插件 | `plugin init` / `check` / `serve`、`plugin user set|remove|list`、`plugin audit tail|stats`、`plugin config list|set`、`plugin service install|uninstall|start|stop|restart|status` |
|
|
114
|
-
| Web 管理台 | `web serve`(可选 `--metrics`)、`web service install|uninstall|start|stop|restart|status`、`web password show|set`、`web audit tail|stats` |
|
|
113
|
+
| 服务端插件 | `plugin init` / `check` / `serve`、`plugin start|stop|restart|status`(后台,非 systemd)、`plugin user set|remove|list`、`plugin audit tail|stats`、`plugin config list|set`、`plugin service install|uninstall|start|stop|restart|status` |
|
|
114
|
+
| Web 管理台 | `web serve`(可选 `--metrics`)、`web start|stop|restart|status`(后台,非 systemd)、`web service install|uninstall|start|stop|restart|status`、`web password show|set`、`web audit tail|stats` |
|
|
115
115
|
|
|
116
116
|
**Web 管理台**——浏览器中的同等能力(`web serve` 启动,默认只绑回环):
|
|
117
117
|
|
|
@@ -231,7 +231,7 @@ $ ./install.sh
|
|
|
231
231
|
注册全局命令
|
|
232
232
|
✓ 已注册:/home/u/.local/bin/frpsctl
|
|
233
233
|
自检
|
|
234
|
-
✓ 命令可用:frpsctl 0.3.
|
|
234
|
+
✓ 命令可用:frpsctl 0.3.3
|
|
235
235
|
|
|
236
236
|
frpsctl 安装完成
|
|
237
237
|
```
|
|
@@ -330,7 +330,7 @@ frpsctl install --with-frpc # frps + frpc
|
|
|
330
330
|
### 验证安装
|
|
331
331
|
|
|
332
332
|
```bash
|
|
333
|
-
frpsctl --version # frpsctl 0.3.
|
|
333
|
+
frpsctl --version # frpsctl 0.3.3
|
|
334
334
|
frpsctl install # 下载 frps 二进制
|
|
335
335
|
frpsctl init # 生成配置(下一步是五分钟上手)
|
|
336
336
|
```
|
|
@@ -872,6 +872,24 @@ Ctrl-C 停止。
|
|
|
872
872
|
浏览器打开上面的 URL,输入口令即进入主界面。会话默认 8 小时(只存服务端内存,
|
|
873
873
|
重启即失效);刷新页面不会掉线(Cookie 还在,前端自动恢复会话)。
|
|
874
874
|
|
|
875
|
+
**后台运行(非 systemd 环境)**:
|
|
876
|
+
|
|
877
|
+
```bash
|
|
878
|
+
frpsctl web start # 后台启动(direct 模式;口令自动落实例文件)
|
|
879
|
+
frpsctl web status # owner=direct;systemd 托管时显示 systemd
|
|
880
|
+
frpsctl web restart # 复用上次参数(--bind 等可覆盖)
|
|
881
|
+
frpsctl web stop # SIGTERM 优雅退出(等待 → SIGKILL 兜底)
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
子进程就是 `web serve`(与 systemd 的 `ExecStart` 同构),进程与启动参数记录在
|
|
885
|
+
`<实例>/web-state.json`;日志写到 `<实例>/web.log`(超过 8 MiB 轮转一次)。
|
|
886
|
+
口令统一走实例内 `web-password`(0600,与 `web password set|show` 同一文件)——
|
|
887
|
+
不再"打印一次即丢失";`--password` 给的值也会先写该文件(避免出现在进程命令行里)。
|
|
888
|
+
|
|
889
|
+
⚠️ **两种托管模式互斥**:systemd 托管(`web service ...`)与 direct 后台
|
|
890
|
+
(`web start`)双向拒绝同时使用,并给出切换命令。容器场景不要用 `web start`
|
|
891
|
+
——容器里前台 `web serve`(进程即容器主进程)才是正确形态。
|
|
892
|
+
|
|
875
893
|
**忘了口令?** 分两种情况:
|
|
876
894
|
|
|
877
895
|
- **systemd 部署**(`web service install` 会把口令写入实例目录的文件):
|
|
@@ -896,14 +914,17 @@ Ctrl-C 停止。
|
|
|
896
914
|
|
|
897
915
|
| 区域 | 内容 | 要点 |
|
|
898
916
|
|------|------|------|
|
|
917
|
+
| 实时概览 | 客户端 / 代理总数 / 当前连接 / 今日入站出站 / TLS 强制(渐变指标条) | 数字来自 dashboard 统计;首次进入滚动到位 |
|
|
899
918
|
| 实例状态 | owner / 状态 / pid / 运行时长 / 版本 / 监听地址 / systemd unit | 二进制版本与磁盘版本不一致时显示"重启生效" |
|
|
900
919
|
| 控制面健康 | L1 / L2 / L3 三层 + gate + 详情 | L2 或 L3 失败时详情直接给出原因 |
|
|
901
|
-
|
|
|
902
|
-
|
|
|
903
|
-
|
|
|
904
|
-
|
|
|
905
|
-
|
|
|
906
|
-
|
|
920
|
+
| 近 7 天流量 | 按天柱状图(渐变蓝=入站 绿=出站) | 悬停显示浮动提示(日期/入出);标题栏带合计;点下方代理行可下钻该代理曲线 |
|
|
921
|
+
| 实时流量 | 页面打开期间的速率面积图(每 5 秒采样一次,累计值差分) | 平滑曲线 + 悬浮十字线提示;采样存本地浏览器,刷新不丢 |
|
|
922
|
+
| 客户端 | name / user / hostname / ip / 状态 / 版本 | 本地过滤 + 点表头排序;双击 name 复制 |
|
|
923
|
+
| 代理 | name / user / 类型 / 端口 / 状态 / 连接 / 今日流量 | **点击任意行展开该代理的 7 天曲线**;表头排序、本地过滤;右上角"清理离线记录" |
|
|
924
|
+
| 日志 | 最近的日志尾部(复用 `log.to` 解析) | ERROR/WARN 着色;向上滚动自动暂停;"复制"按钮一键复制 |
|
|
925
|
+
|
|
926
|
+
**交互速查**:快捷键 `g d` / `g c` / `g a` 切换视图、`r` 刷新、`/` 聚焦过滤框、
|
|
927
|
+
`Esc` 关闭弹层;危险操作走自绘确认弹层(可 Enter/Esc);审计页有独立过滤框。
|
|
907
928
|
|
|
908
929
|
页面顶部的**横幅**会明确报告异常:
|
|
909
930
|
|
|
@@ -1026,7 +1047,9 @@ frp 的服务端插件是一个 HTTP 回调:frps 在 `Login` / `NewProxy` 等
|
|
|
1026
1047
|
```bash
|
|
1027
1048
|
frpsctl plugin init # 生成策略模板(0600,默认 fail-closed)
|
|
1028
1049
|
frpsctl plugin check # 离线校验 + 试算典型裁决
|
|
1029
|
-
frpsctl plugin serve #
|
|
1050
|
+
frpsctl plugin serve # 前台启动(只允许绑回环)
|
|
1051
|
+
frpsctl plugin start # 后台启动(direct 模式,非 systemd;SIGTERM 先刷审计再退出)
|
|
1052
|
+
frpsctl plugin status # 托管状态(systemd / direct / none)
|
|
1030
1053
|
```
|
|
1031
1054
|
|
|
1032
1055
|
策略里的用户可以用命令维护——不必手写 JSON(写入前用与 `plugin check` 相同的
|
|
@@ -1670,6 +1693,8 @@ fail)——它们是"插件真的接得住 frp 调用"的唯一证明,因此
|
|
|
1670
1693
|
| **Web 不做 DOM 级前端测试框架** | 引入 jsdom/构建链会破坏"单文件零依赖"这个安全资产;语法与静态纪律由 CI 守卫,纯函数由 node 动态断言(v0.3.0 覆盖审计渲染等 6 个),DOM 分支仍靠人工点验(残余风险已记账) |
|
|
1671
1694
|
| **不实现 OIDC 协议** | `auth.method = "oidc"` 的配置完整性与 doctor 提示已支持(v0.3.0);OIDC 协议本身由 frps 实现——本工具绝不重新实现 frp 已有能力 |
|
|
1672
1695
|
| **一个 Web 进程服务一个实例** | 多实例请起多个 `web serve`(各自 `--instance` 区分);管理台不做实例切换器 |
|
|
1696
|
+
| **direct 后台无开机自启** | `web start` / `plugin start` 是"进程级后台化"(非 systemd):机器重启后不自启——systemd 环境用 `service install`,容器用 restart policy(v0.3.3) |
|
|
1697
|
+
| **systemd 与 direct 后台互斥** | 同一实例的 Web/插件只能被一种模式托管;两个方向都会拒绝并给出切换命令(v0.3.3)。`uninstall` 对运行中的 direct 服务同样拒绝(`--force` 先停),不留孤儿 |
|
|
1673
1698
|
|
|
1674
1699
|
---
|
|
1675
1700
|
|
|
@@ -87,8 +87,8 @@ CLI 负责精确控制与脚本化,Web 管理台负责可视化与日常操作
|
|
|
87
87
|
| 观测与运维 | `clients` / `proxies` / `traffic` / `instances` / `doctor` / `prune` / `capabilities`(能力清单) |
|
|
88
88
|
| 卸载 | `uninstall`(`--all` / `--keep-data` / `--keep-bin` / `--force`) |
|
|
89
89
|
| systemd 集成 | `service install` / `uninstall` / `status` / `logs` |
|
|
90
|
-
| 服务端插件 | `plugin init` / `check` / `serve`、`plugin user set|remove|list`、`plugin audit tail|stats`、`plugin config list|set`、`plugin service install|uninstall|start|stop|restart|status` |
|
|
91
|
-
| Web 管理台 | `web serve`(可选 `--metrics`)、`web service install|uninstall|start|stop|restart|status`、`web password show|set`、`web audit tail|stats` |
|
|
90
|
+
| 服务端插件 | `plugin init` / `check` / `serve`、`plugin start|stop|restart|status`(后台,非 systemd)、`plugin user set|remove|list`、`plugin audit tail|stats`、`plugin config list|set`、`plugin service install|uninstall|start|stop|restart|status` |
|
|
91
|
+
| Web 管理台 | `web serve`(可选 `--metrics`)、`web start|stop|restart|status`(后台,非 systemd)、`web service install|uninstall|start|stop|restart|status`、`web password show|set`、`web audit tail|stats` |
|
|
92
92
|
|
|
93
93
|
**Web 管理台**——浏览器中的同等能力(`web serve` 启动,默认只绑回环):
|
|
94
94
|
|
|
@@ -208,7 +208,7 @@ $ ./install.sh
|
|
|
208
208
|
注册全局命令
|
|
209
209
|
✓ 已注册:/home/u/.local/bin/frpsctl
|
|
210
210
|
自检
|
|
211
|
-
✓ 命令可用:frpsctl 0.3.
|
|
211
|
+
✓ 命令可用:frpsctl 0.3.3
|
|
212
212
|
|
|
213
213
|
frpsctl 安装完成
|
|
214
214
|
```
|
|
@@ -307,7 +307,7 @@ frpsctl install --with-frpc # frps + frpc
|
|
|
307
307
|
### 验证安装
|
|
308
308
|
|
|
309
309
|
```bash
|
|
310
|
-
frpsctl --version # frpsctl 0.3.
|
|
310
|
+
frpsctl --version # frpsctl 0.3.3
|
|
311
311
|
frpsctl install # 下载 frps 二进制
|
|
312
312
|
frpsctl init # 生成配置(下一步是五分钟上手)
|
|
313
313
|
```
|
|
@@ -849,6 +849,24 @@ Ctrl-C 停止。
|
|
|
849
849
|
浏览器打开上面的 URL,输入口令即进入主界面。会话默认 8 小时(只存服务端内存,
|
|
850
850
|
重启即失效);刷新页面不会掉线(Cookie 还在,前端自动恢复会话)。
|
|
851
851
|
|
|
852
|
+
**后台运行(非 systemd 环境)**:
|
|
853
|
+
|
|
854
|
+
```bash
|
|
855
|
+
frpsctl web start # 后台启动(direct 模式;口令自动落实例文件)
|
|
856
|
+
frpsctl web status # owner=direct;systemd 托管时显示 systemd
|
|
857
|
+
frpsctl web restart # 复用上次参数(--bind 等可覆盖)
|
|
858
|
+
frpsctl web stop # SIGTERM 优雅退出(等待 → SIGKILL 兜底)
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
子进程就是 `web serve`(与 systemd 的 `ExecStart` 同构),进程与启动参数记录在
|
|
862
|
+
`<实例>/web-state.json`;日志写到 `<实例>/web.log`(超过 8 MiB 轮转一次)。
|
|
863
|
+
口令统一走实例内 `web-password`(0600,与 `web password set|show` 同一文件)——
|
|
864
|
+
不再"打印一次即丢失";`--password` 给的值也会先写该文件(避免出现在进程命令行里)。
|
|
865
|
+
|
|
866
|
+
⚠️ **两种托管模式互斥**:systemd 托管(`web service ...`)与 direct 后台
|
|
867
|
+
(`web start`)双向拒绝同时使用,并给出切换命令。容器场景不要用 `web start`
|
|
868
|
+
——容器里前台 `web serve`(进程即容器主进程)才是正确形态。
|
|
869
|
+
|
|
852
870
|
**忘了口令?** 分两种情况:
|
|
853
871
|
|
|
854
872
|
- **systemd 部署**(`web service install` 会把口令写入实例目录的文件):
|
|
@@ -873,14 +891,17 @@ Ctrl-C 停止。
|
|
|
873
891
|
|
|
874
892
|
| 区域 | 内容 | 要点 |
|
|
875
893
|
|------|------|------|
|
|
894
|
+
| 实时概览 | 客户端 / 代理总数 / 当前连接 / 今日入站出站 / TLS 强制(渐变指标条) | 数字来自 dashboard 统计;首次进入滚动到位 |
|
|
876
895
|
| 实例状态 | owner / 状态 / pid / 运行时长 / 版本 / 监听地址 / systemd unit | 二进制版本与磁盘版本不一致时显示"重启生效" |
|
|
877
896
|
| 控制面健康 | L1 / L2 / L3 三层 + gate + 详情 | L2 或 L3 失败时详情直接给出原因 |
|
|
878
|
-
|
|
|
879
|
-
|
|
|
880
|
-
|
|
|
881
|
-
|
|
|
882
|
-
|
|
|
883
|
-
|
|
897
|
+
| 近 7 天流量 | 按天柱状图(渐变蓝=入站 绿=出站) | 悬停显示浮动提示(日期/入出);标题栏带合计;点下方代理行可下钻该代理曲线 |
|
|
898
|
+
| 实时流量 | 页面打开期间的速率面积图(每 5 秒采样一次,累计值差分) | 平滑曲线 + 悬浮十字线提示;采样存本地浏览器,刷新不丢 |
|
|
899
|
+
| 客户端 | name / user / hostname / ip / 状态 / 版本 | 本地过滤 + 点表头排序;双击 name 复制 |
|
|
900
|
+
| 代理 | name / user / 类型 / 端口 / 状态 / 连接 / 今日流量 | **点击任意行展开该代理的 7 天曲线**;表头排序、本地过滤;右上角"清理离线记录" |
|
|
901
|
+
| 日志 | 最近的日志尾部(复用 `log.to` 解析) | ERROR/WARN 着色;向上滚动自动暂停;"复制"按钮一键复制 |
|
|
902
|
+
|
|
903
|
+
**交互速查**:快捷键 `g d` / `g c` / `g a` 切换视图、`r` 刷新、`/` 聚焦过滤框、
|
|
904
|
+
`Esc` 关闭弹层;危险操作走自绘确认弹层(可 Enter/Esc);审计页有独立过滤框。
|
|
884
905
|
|
|
885
906
|
页面顶部的**横幅**会明确报告异常:
|
|
886
907
|
|
|
@@ -1003,7 +1024,9 @@ frp 的服务端插件是一个 HTTP 回调:frps 在 `Login` / `NewProxy` 等
|
|
|
1003
1024
|
```bash
|
|
1004
1025
|
frpsctl plugin init # 生成策略模板(0600,默认 fail-closed)
|
|
1005
1026
|
frpsctl plugin check # 离线校验 + 试算典型裁决
|
|
1006
|
-
frpsctl plugin serve #
|
|
1027
|
+
frpsctl plugin serve # 前台启动(只允许绑回环)
|
|
1028
|
+
frpsctl plugin start # 后台启动(direct 模式,非 systemd;SIGTERM 先刷审计再退出)
|
|
1029
|
+
frpsctl plugin status # 托管状态(systemd / direct / none)
|
|
1007
1030
|
```
|
|
1008
1031
|
|
|
1009
1032
|
策略里的用户可以用命令维护——不必手写 JSON(写入前用与 `plugin check` 相同的
|
|
@@ -1647,6 +1670,8 @@ fail)——它们是"插件真的接得住 frp 调用"的唯一证明,因此
|
|
|
1647
1670
|
| **Web 不做 DOM 级前端测试框架** | 引入 jsdom/构建链会破坏"单文件零依赖"这个安全资产;语法与静态纪律由 CI 守卫,纯函数由 node 动态断言(v0.3.0 覆盖审计渲染等 6 个),DOM 分支仍靠人工点验(残余风险已记账) |
|
|
1648
1671
|
| **不实现 OIDC 协议** | `auth.method = "oidc"` 的配置完整性与 doctor 提示已支持(v0.3.0);OIDC 协议本身由 frps 实现——本工具绝不重新实现 frp 已有能力 |
|
|
1649
1672
|
| **一个 Web 进程服务一个实例** | 多实例请起多个 `web serve`(各自 `--instance` 区分);管理台不做实例切换器 |
|
|
1673
|
+
| **direct 后台无开机自启** | `web start` / `plugin start` 是"进程级后台化"(非 systemd):机器重启后不自启——systemd 环境用 `service install`,容器用 restart policy(v0.3.3) |
|
|
1674
|
+
| **systemd 与 direct 后台互斥** | 同一实例的 Web/插件只能被一种模式托管;两个方向都会拒绝并给出切换命令(v0.3.3)。`uninstall` 对运行中的 direct 服务同样拒绝(`--force` 先停),不留孤儿 |
|
|
1650
1675
|
|
|
1651
1676
|
---
|
|
1652
1677
|
|
|
@@ -3531,3 +3531,132 @@ Group` 的**实际生效值**为准(留档仅回退)。探测失败 → WARN
|
|
|
3531
3531
|
| 数字 UID 的"无账户"形态(unit `User=1000` 而系统无该 UID) | 不支持:解析要求 UID 已存在——无账户的裸 UID 无法被 `userdel`/`systemctl show` 等下游一致处理,拒绝优于半可用 |
|
|
3532
3532
|
| `--create-user` 自动建非同名组 | 不做:只随用户建同名组(`--user-group`);显式 `--group` 要求已存在,避免乱建组 |
|
|
3533
3533
|
| 服务账户的自动删除 | 不做:账户可能另有用途,卸载只提示(遵循"不确定就拒绝") |
|
|
3534
|
+
|
|
3535
|
+
---
|
|
3536
|
+
|
|
3537
|
+
## 26. 第十三轮迭代(v0.3.3:后台服务与 Web 体验)
|
|
3538
|
+
|
|
3539
|
+
**systemd 之外的第二种托管形态 + 管理台视觉/交互大改**。此前的现实痛点:
|
|
3540
|
+
容器与无 systemd 主机上,Web 管理台与插件服务只能前台运行或 `nohup`(口令进
|
|
3541
|
+
日志、无 pid 管理、无法安全停止);Web UI 自 v0.2.4 以来没有结构性升级。
|
|
3542
|
+
|
|
3543
|
+
方法:完整通读 Web/插件前后端(`web/server.py` 571 行、`web/api.py` 861、
|
|
3544
|
+
`web/auth.py`、前端 `index.html` 1335 行、`plugin/server.py` 372 等)+ 进程
|
|
3545
|
+
原语与 lifecycle 复用面评估 + 前端守卫约束复核。
|
|
3546
|
+
|
|
3547
|
+
统计:新增 **1 个 core 模块**(`core/serve_runtime.py`,约 430 行)、**8 个
|
|
3548
|
+
叶子命令**(55 → 63)、**前端三大块重构**(设计系统/图表/交互,单文件
|
|
3549
|
+
62KB → 84KB);新增 **39 条测试**(828 → 869;非契约 798 → 839);契约快照
|
|
3550
|
+
+8 命令;前端守卫 +3 条(15 → 18)。
|
|
3551
|
+
|
|
3552
|
+
### 26.1 后台服务运行时(`core/serve_runtime.py`)
|
|
3553
|
+
|
|
3554
|
+
设计决策(与 frps direct 模式同纪律,而非另造 daemon):
|
|
3555
|
+
|
|
3556
|
+
| 决策 | 内容 | 理由 |
|
|
3557
|
+
|------|------|------|
|
|
3558
|
+
| 启动机制 | `start` = **重新 exec `frpsctl web|plugin serve`**(`start_new_session=True`、stdout/stderr → 日志) | 与 systemd `ExecStart` 逐字同构:优雅退出、审计刷盘等语义零分叉;无需 fork/daemonize 代码 |
|
|
3559
|
+
| 早退检测 | 派生后 0.7s 连续存活 + 端口 TCP 探活(3s) | 端口占用/启动即崩当场报告并回显日志尾部,不留半活进程 |
|
|
3560
|
+
| 状态文件 | `<实例>/<key>-state.json`(0600):pid/start_time/binary/argv/args/log/host/port | `restart` 复用参数、`status` 可查、`uninstall` 能发现孤儿 |
|
|
3561
|
+
| 三重校验 | pid 存活 + 启动时刻一致 + 命令行含 `serve` 标记 | state 只由本工具写;多一维把"同可执行文件的其它长命进程"排除在外 |
|
|
3562
|
+
| 停止 | SIGTERM → 等待 10s → 复核身份 → SIGKILL(5s) | 与 frps `stop` 同型;plugin 的 SIGTERM 会先刷审计 |
|
|
3563
|
+
| 日志 | `<实例>/<key>.log`(0600),启动时 >8 MiB 轮转 `.1` | 后台模式的 stderr 不能丢;单份历史足够 |
|
|
3564
|
+
| 口令 | `web start` 统一落实例 `web-password`;`--password`/env 先写文件,argv 只出现路径 | 口令可读回;明文不进进程命令行(ps 可见面) |
|
|
3565
|
+
|
|
3566
|
+
`probe()` 的五态归属(NONE/DIRECT/FOREIGN/STALE/CORRUPTED)供
|
|
3567
|
+
`status`/`uninstall`/`doctor` 三处共用——损坏与"指向外人"都**拒绝操作**而不是
|
|
3568
|
+
猜测(ADR-7)。
|
|
3569
|
+
|
|
3570
|
+
**互斥(双向)**:`web start` 对 active 的 systemd unit 拒绝(提示
|
|
3571
|
+
`service start`);`service install/start/restart` 对存活的 direct 进程拒绝
|
|
3572
|
+
(提示 `stop`)。`service status` 保持 systemd 专项视图,`web status` 提供
|
|
3573
|
+
统一 owner 视图(systemd 优先,探测失败降级可见)。
|
|
3574
|
+
|
|
3575
|
+
**孤儿防护**:`uninstall` 预检新增 direct 服务——运行中拒绝(`--force` 在
|
|
3576
|
+
`_ensure_stopped` 阶段先停再卸);状态损坏同样拒绝。`doctor` 新增
|
|
3577
|
+
`_check_local_services`:运行中 INFO、陈旧 INFO、损坏 WARN、身份不符 ERROR。
|
|
3578
|
+
|
|
3579
|
+
### 26.2 Web UI/UX(v0.3.3)
|
|
3580
|
+
|
|
3581
|
+
**设计系统(极光 · 玻璃 · 霓虹)**:CSS 令牌扩展(accent 软色/渐变、aurora
|
|
3582
|
+
三层径向、glass/glass-border、ring、三档阴影、hero 渐变);`body` 极光背景
|
|
3583
|
+
(fixed 多层 radial-gradient);卡片玻璃化 + hover 抬升;品牌与导航指示条
|
|
3584
|
+
渐变;状态呼吸灯;渐变指标条(Hero,首帧数字滚动);骨架屏与空态;自绘
|
|
3585
|
+
确认弹层(替代原生 `confirm`,Enter/Esc/点击遮罩);toast 图标 + 进度条 +
|
|
3586
|
+
滑入;登录页重做;主题切换过渡。
|
|
3587
|
+
|
|
3588
|
+
**图表 2.0**:柱状与折线改 SVG 渐变填充(`<defs>` 渐变 + `stop` 类由 CSS
|
|
3589
|
+
变量着色——主题切换即时生效);实时曲线 Catmull-Rom → 贝塞尔平滑 + 面积
|
|
3590
|
+
填充;悬浮十字线 + **SVG 内自绘 tooltip**(位置用 SVG 属性设置,不触碰
|
|
3591
|
+
内联 style 禁令)。纯函数 `smoothPath` 可直接被 node 守卫执行。
|
|
3592
|
+
|
|
3593
|
+
**交互**:快捷键(`g d/g c/g a`、`r`、`/`、`Esc`);客户端/代理/审计本地
|
|
3594
|
+
过滤(`filterRows` 纯函数);客户端/代理点表头排序(`sortRows` 纯函数,
|
|
3595
|
+
数值列按数值比较);双击复制名称(clipboard,失败降级 toast);日志
|
|
3596
|
+
ERROR/WARN 着色(按行文本节点渲染)与一键复制;视图切换动画;
|
|
3597
|
+
`prefers-reduced-motion` 下全部动画关闭。
|
|
3598
|
+
|
|
3599
|
+
**红线保持**(守卫自动核对):单文件、零外部资源、无 `innerHTML`、无内联
|
|
3600
|
+
style 属性、无 JS style 赋值、`__CSP_NONCE__` 恰 3 处、CSS 变量双向对齐、
|
|
3601
|
+
图表类有样式。新增守卫:新组件类样式齐全 / reduced-motion 与极光存在 /
|
|
3602
|
+
原生 `confirm|alert` 禁用。
|
|
3603
|
+
|
|
3604
|
+
### 26.3 测试与验收
|
|
3605
|
+
|
|
3606
|
+
- **单元 24 条**(`TestServeRuntime` 16 + `TestUninstallLocalServices` 5,
|
|
3607
|
+
全部真进程):启动记录与探活、双起拒绝、陈旧清理、外人拒绝、停止与
|
|
3608
|
+
SIGKILL 兜底、早退/端口未就绪清理、损坏/缺字段拒绝、日志轮转与 tail、
|
|
3609
|
+
uninstall 预检/强制停止、doctor 发现。
|
|
3610
|
+
- **CLI 12 条**(`TestServeBackgroundCommands`):start JSON 与口令落盘
|
|
3611
|
+
(argv 无明文)、非回环拒绝、systemd 互斥(两个方向)、stop、status
|
|
3612
|
+
三态、plugin 接线。
|
|
3613
|
+
- **前端守卫 +3**:组件类样式齐全、reduced-motion 与极光令牌、原生弹窗禁用。
|
|
3614
|
+
- **端到端冒烟(真实进程)**:`web start` → HTTP 200 → `status`(direct)
|
|
3615
|
+
→ `stop`(进程确亡);`plugin start` → `/healthz` 200 → `stop`(审计刷盘);
|
|
3616
|
+
direct 存活时 `service start` 拒绝(exit 11)。
|
|
3617
|
+
- **契约快照**:+8 命令(392 行增量逐行核对:选项/默认/重复性)。
|
|
3618
|
+
- **最终验收**:全量 **869 passed / 0 skipped**(非契约 839),覆盖率 **85.94%**(新模块与命令面扩大分母;门禁 80% 通过)。
|
|
3619
|
+
|
|
3620
|
+
### 26.5 实施期 review 补正
|
|
3621
|
+
|
|
3622
|
+
全部 diff 逐行审查 + 对抗性实测(真实进程)发现并补正 1 处缺陷:
|
|
3623
|
+
|
|
3624
|
+
| # | 项 | 问题 | 补正 |
|
|
3625
|
+
|---|----|------|------|
|
|
3626
|
+
| R-1 | **`restart` 参数复用失效(实测复现)** | `web|plugin restart` 先 `stop_background`(会删除状态文件)再进 `_start_direct` 读旧参数——此时状态文件已不存在,`--bind` 等静默回落默认值 | 改为**先读后停**:restart 命令体先 `read_state` 保存旧参数,经 `fallback_args` 传入启动实现;新增"事件顺序"守卫测试(断言 read 先于 stop)并做反向验证(恢复旧顺序 → 守卫红) |
|
|
3627
|
+
|
|
3628
|
+
| R-2 | **测试 flaky:随机口令以 `-` 开头(实测定位)** | `test_config_set_noop_masks_secret` 从配置提取的随机口令(base64url 字符集)约 1.6% 概率以 `-` 开头,被 CLI 解析成选项(`No such option: -e`)——全量运行约 1/60 概率偶发 | 测试改用固定且以 `-e-` 开头的口令并以 `--` 分隔,顺带固化"`--` 之后全是位置参数"的语义;连跑 5 次确定性验证。产品行为本身正确(click 惯例:值以 `-` 开头需 `--`) |
|
|
3629
|
+
| R-3 | **`restart` 不复用外部口令文件(最后一轮 review)** | `--password-file` 指向实例外文件时,restart 未显式给该参数会静默回落默认实例口令文件(口令来源发生变化) | `_start_direct` 从持久化 args 复用 `password_file` 路径(外部文件被删时明确报错而不静默生成);测试断言 argv 路径复用 + 真实端到端验证 |
|
|
3630
|
+
| R-4 | **代理表空态被展开集合吞掉(最后一轮 review)** | 过滤无结果但此前展开过代理行时,表格区域空白(没有空态提示) | 空态条件简化为 `if (!rows.length)`(无行即显示,不再受展开集合影响) |
|
|
3631
|
+
| R-5 | **插件并发测试 flaky(最后一轮 review 实测)** | `test_exhausted_workers_get_503` 只接受 HTTP 503,而 worker 占满时服务端 close 与客户端发送的竞态会偶发触发内核 TCP 重置(连接层 OSError)——与 v0.3.1 修过的 burst 测试同一条语义,当时漏了这条 | 断言放宽为 `(HTTPError, OSError)` 且 HTTPError 必须 503(两者对 frp 都是"该操作失败",README 已知边界);`TestBoundedConcurrency` 连跑 10 次确定性验证 |
|
|
3632
|
+
|
|
3633
|
+
其余审查结论:三重校验/互斥/孤儿防护的守护测试均通过反向验证(短路实现即
|
|
3634
|
+
变红);真实进程冒烟覆盖 start→HTTP→restart→stop、损坏状态拒绝(exit 3)、
|
|
3635
|
+
uninstall 无 force 拒绝(exit 11)/`--force` 先停。
|
|
3636
|
+
|
|
3637
|
+
**方案逐项对账的自检补正**("所有项是否完整实现"的系统复查):按 §26 方案
|
|
3638
|
+
的 D1–D10、W1–W10 与 UI 验收清单逐条核对,发现 6 处未落地/不到位的项并全部
|
|
3639
|
+
补齐:
|
|
3640
|
+
|
|
3641
|
+
| # | 方案条目 | 缺口 | 补正 |
|
|
3642
|
+
|---|----------|------|------|
|
|
3643
|
+
| S-1 | D10 / W5:doctor 的**进程/端口检查(P1)** | 只实现了进程状态,未做端口一致性检查 | RUNNING 服务探测记录端口:连不上 → WARN"可能已半死"(只读 TCP 探针)+ 测试 |
|
|
3644
|
+
| S-2 | UI 清单:Hero"趋势箭头" | 指标条无趋势指示 | 与上一次刷新的数值对比,显示 `▲/▼ 增量`(仅纯数字指标) |
|
|
3645
|
+
| S-3 | UI 底线:"触控目标 ≥40px" | 未实现 | `@media (pointer: coarse)` 下按钮/输入/导航放大到 ≥40px |
|
|
3646
|
+
| S-4 | UI 清单:"复制(名称/端口…)" | 只做了名称复制 | 代理端口单元格双击复制 |
|
|
3647
|
+
| S-5 | 五、测试计划:"端到端(真进程)" | 只有 sleeper 进程的原语测试与手工冒烟,缺**真链路自动化** | 新增 `TestServeEndToEnd`:真 `python -m frpsctl web serve` → HTTP 200 → stop;真 `plugin serve` → Login 裁决 → **stop 后审计落盘断言** |
|
|
3648
|
+
| S-6 | W4:"互斥矩阵 4 场景" | 缺 plugin 侧两个方向 | 补 `plugin start` 拒 systemd active、`plugin service start` 拒 direct 存活 |
|
|
3649
|
+
|
|
3650
|
+
(测试计划中"+55~70 条"的预估未达成:实际 +39——e2e 与互斥复用既有基建后
|
|
3651
|
+
写得紧凑。预估偏差如实记录,不以凑数补测试。)
|
|
3652
|
+
|
|
3653
|
+
### 26.4 未做与边界(明确记账)
|
|
3654
|
+
|
|
3655
|
+
| 项 | 结论 |
|
|
3656
|
+
|----|------|
|
|
3657
|
+
| direct 后台的开机自启 | 不做:systemd 场景用 `service install`;容器用 restart policy。direct 是"进程级后台化",定位如此 |
|
|
3658
|
+
| 容器内 direct 后台 | 不推荐(文档说明):容器里前台 `serve`(进程即容器主进程)才是正确形态 |
|
|
3659
|
+
| 后台服务的 stdout 之外的运行日志 | 不做:`serve` 自身日志(访问日志等)走 `--access-log` 进同一文件;不引入 journald 依赖 |
|
|
3660
|
+
| per-instance 多 Web 进程 | 不变:一个 Web 进程服务一个实例 |
|
|
3661
|
+
| WebSocket/SSE | 不变:5 秒轮询(既有边界) |
|
|
3662
|
+
| 前端 DOM 级测试框架 | 不变:node 纯函数 + 静态守卫 + HTTP 全路由 + 手工点验(记账同上) |
|