fh_tool-cli 0.2.0__tar.gz → 0.2.2__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.
Files changed (57) hide show
  1. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/PKG-INFO +55 -42
  2. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/README.md +52 -41
  3. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/pyproject.toml +3 -1
  4. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/__init__.py +1 -1
  5. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/backup.py +1 -1
  6. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/cli.py +312 -116
  7. fh_tool_cli-0.2.2/src/fh_tool_cli/click_cli.py +297 -0
  8. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/commands/web.py +52 -61
  9. fh_tool_cli-0.2.2/src/fh_tool_cli/credential_sources.py +47 -0
  10. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/credentials.py +1 -1
  11. fh_tool_cli-0.2.2/src/fh_tool_cli/output.py +48 -0
  12. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/parser.py +80 -63
  13. fh_tool_cli-0.2.2/src/fh_tool_cli/risk.py +45 -0
  14. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/upload.py +1 -1
  15. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli.egg-info/PKG-INFO +55 -42
  16. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli.egg-info/SOURCES.txt +4 -0
  17. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli.egg-info/requires.txt +2 -0
  18. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_account.py +47 -0
  19. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_cli_risk.py +52 -50
  20. fh_tool_cli-0.2.2/tests/test_click_cli.py +72 -0
  21. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_config_decrypt.py +7 -0
  22. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_credentials.py +42 -3
  23. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_extracted_helpers.py +14 -29
  24. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_parser_registration.py +15 -17
  25. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_web_ajax_post.py +10 -27
  26. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_web_write_payloads.py +3 -4
  27. fh_tool_cli-0.2.0/src/fh_tool_cli/risk.py +0 -24
  28. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/setup.cfg +0 -0
  29. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/account.py +0 -0
  30. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/argparse_utils.py +0 -0
  31. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/backends/__init__.py +0 -0
  32. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/backends/cfg_cmd.py +0 -0
  33. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/backends/fh_tool.py +0 -0
  34. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/backends/local_vm.py +0 -0
  35. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/backends/telnet.py +0 -0
  36. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/backends/web_ajax.py +0 -0
  37. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/client.py +0 -0
  38. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/commands/__init__.py +0 -0
  39. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/config_decrypt.py +0 -0
  40. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/config_store.py +0 -0
  41. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/crypto.py +0 -0
  42. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/diagnostics.py +0 -0
  43. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/errors.py +0 -0
  44. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/remote.py +0 -0
  45. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/web_discovery.py +0 -0
  46. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli/web_writes.py +0 -0
  47. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli.egg-info/dependency_links.txt +0 -0
  48. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli.egg-info/entry_points.txt +0 -0
  49. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/src/fh_tool_cli.egg-info/top_level.txt +0 -0
  50. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_backup.py +0 -0
  51. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_cfg_cmd.py +0 -0
  52. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_diagnostics.py +0 -0
  53. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_local_vm_integration.py +0 -0
  54. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_remote.py +0 -0
  55. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_upload.py +0 -0
  56. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_web_ajax.py +0 -0
  57. {fh_tool_cli-0.2.0 → fh_tool_cli-0.2.2}/tests/test_web_discovery.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fh_tool-cli
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: 用于本地管理 FiberHome fh_tool 接口的 Python CLI
5
5
  Author: Gxxk
6
6
  License-Expression: AGPL-3.0-or-later
@@ -9,8 +9,10 @@ Classifier: Programming Language :: Python :: 3
9
9
  Classifier: Topic :: System :: Networking
10
10
  Requires-Python: >=3.11
11
11
  Description-Content-Type: text/markdown
12
+ Requires-Dist: click>=8.1.0
12
13
  Requires-Dist: cryptography>=42.0.0
13
14
  Requires-Dist: requests>=2.31.0
15
+ Requires-Dist: rich>=13.7.0
14
16
 
15
17
  # fh_tool-cli
16
18
 
@@ -38,6 +40,18 @@ uv run fh-tool --help
38
40
 
39
41
  下文示例中的 `fh-tool ...` 如果是在源码目录内运行,可以统一写成 `uv run fh-tool ...`。
40
42
 
43
+ ## CLI 输出和日志
44
+
45
+ CLI 入口使用 Click,错误和日志输出使用 Rich。命令结果只写 stdout;错误、警告和日志写 stderr,便于脚本把 stdout 当作数据流处理。
46
+
47
+ ```bash
48
+ fh-tool --verbose probe --json
49
+ fh-tool --quiet config show
50
+ fh-tool --log-file fh-tool.log dev-info
51
+ ```
52
+
53
+ `--json` 输出稳定的 machine-readable JSON,不混入日志或样式。当前默认人类输出仍保持 pretty JSON,以兼容已有脚本;后续可以在不影响 `--json` 的前提下逐步增加表格化输出。
54
+
41
55
  ## 快速配置
42
56
 
43
57
  保存默认 IP/MAC:
@@ -103,7 +117,8 @@ fh-tool credentials derive --kind hg5143f-telnet --mac AABBCCDDEEFF
103
117
  打开 runtime Telnet:
104
118
 
105
119
  ```bash
106
- fh-tool telnet enable --yes
120
+ fh-tool telnet enable
121
+ fh-tool telnet enable --confirm
107
122
  ```
108
123
 
109
124
  检查端口:
@@ -134,7 +149,7 @@ fh-tool wan list --backend local-vm
134
149
 
135
150
  `local-vm` 只是在本机 proot VM 内执行厂商 `cfg_cmd`。`--vm-root` 必须指向 VM 工作区目录,也就是包含 `bin/proot-shell` 和 `rootfs-vm/fhrom/bin/cfg_cmd` 的目录;默认是 `/mnt/dev-cold/HG5143F-ONU-vm`。不要把它指到里面的 `rootfs-vm/`。
136
151
 
137
- Web AJAX 读取命令只读。需要复用已有 Web session 时加 `--sessionid`;需要登录时可显式传 `--password-stdin` 或 `--password`。未显式提供密码时默认 `--username useradmin --password-source auto`,会依次尝试 `GetAdminAccount` 和 cfg 路径读取 Web superadmin 密码;失败不会阻塞只读抓取。sessionid、密码、LOID、PPPoE 等敏感字段默认会脱敏;只有显式加 `--reveal-secrets` 才输出明文。
152
+ Web AJAX 读取命令只读。需要复用已有 Web session 时加 `--sessionid`;需要登录时可显式传 `--password-stdin` 或 `--password`。未显式提供密码时默认 `--username useradmin --password-source auto`,会依次尝试 `GetAdminAccount` 和 cfg 路径读取 Web superadmin 密码;cfg 来源需要 Telnet 时会默认使用 HG5143F 派生 Telnet 凭据 fallback,可用 `--no-derived-credentials` 关闭。失败不会阻塞只读抓取。sessionid、密码、LOID、PPPoE 等敏感字段默认会脱敏;只有显式加 `--reveal-secrets` 才输出明文。
138
153
 
139
154
  后台 AJAX 接口发现以 live discovery 为主路径,不需要 HAR,也不需要 rootfs:
140
155
 
@@ -146,24 +161,25 @@ fh-tool web discover merge --input web-ajax-catalog.json --input static-web-ajax
146
161
 
147
162
  `live` 只探测只读 `get_*/query_*/show_*` 候选;写候选只进入 catalog,不会自动 POST。`static` 是补充路径,用于从 rootfs/备份目录扫描 HTML/JS/CSS 里的 `ajaxmethod`、参数名和上下文。
148
163
 
149
- Web AJAX 写接口默认只做 dry-run。执行 POST 需要先完成备份,并显式加 `--execute --backup-confirmed --yes --danger`:
164
+ Web AJAX 写接口默认只做 dry-run,并会提示重新运行时加 `--confirm` 才会执行 POST:
150
165
 
151
166
  ```bash
152
167
  fh-tool web ajax post set_wan_info --param VLANID=100
153
168
  fh-tool web ajax replay --catalog web-ajax-catalog.json --method set_wan_info --param VLANID=100
154
169
  fh-tool web port-mapping set --operation add --wan-index 1 --wan-session-index 1 --wan-iporppp ppp --external-port 8080 --protocol tcp --internal-client 192.168.1.2 --internal-port 80
155
170
  fh-tool web vlanbind set --operation add --if-name eth1 --user-vlan 100 --wan-vlan 100
156
- fh-tool web firewall set --enable 1 --level medium --dos-enable 1 --ipv6-enable 1 --execute --backup-confirmed --yes --danger
157
- fh-tool web services set --service telnet --enabled 0 --execute --backup-confirmed --yes --danger
171
+ fh-tool web firewall set --enable 1 --level medium --dos-enable 1 --ipv6-enable 1 --confirm
172
+ fh-tool web services set --service telnet --enabled 0 --confirm
158
173
  ```
159
174
 
160
- 常规 Web 写接口优先使用 typed 参数。`web ajax post` 和 `web ajax replay` 支持任意已知或未知 AJAX method,默认只输出计划,不发 POST;执行同样必须加 `--execute --backup-confirmed --yes --danger`,且默认拒绝空 payload。`--json-payload` 和可重复的 `--param k=v` 仍保留为固件差异逃生口,合并顺序是 typed 参数、JSON、最后 `--param` 覆盖。
175
+ 常规 Web 写接口优先使用 typed 参数。`web ajax post` 和 `web ajax replay` 支持任意已知或未知 AJAX method,默认只输出计划,不发 POST;执行必须加 `--confirm`,且默认拒绝空 payload。`--json-payload` 和可重复的 `--param k=v` 仍保留为固件差异逃生口,合并顺序是 typed 参数、JSON、最后 `--param` 覆盖。旧的确认参数会直接报弃用错误。
161
176
 
162
- Telnet/cfg/诊断命令默认不会自动套用派生凭据。如果设备仍是 HG5143F 默认 Telnet 规则,并且已提供或保存 MAC,可以显式加 `--use-derived-credentials` 作为 fallback:
177
+ Telnet/cfg/诊断命令在未显式传 Telnet 密码时,会默认使用 HG5143F 派生 Telnet 凭据 fallback;显式传入的用户名/密码始终优先。如果设备不是该规则,或需要保留空凭据/自定义认证,可加 `--no-derived-credentials` 关闭。`--use-derived-credentials` 仍作为兼容参数接受:
163
178
 
164
179
  ```bash
165
- fh-tool cfg get InternetGatewayDevice.DeviceInfo.Manufacturer --use-derived-credentials
166
- fh-tool wan list --use-derived-credentials
180
+ fh-tool cfg get InternetGatewayDevice.DeviceInfo.Manufacturer
181
+ fh-tool wan list
182
+ fh-tool cfg get InternetGatewayDevice.DeviceInfo.Manufacturer --no-derived-credentials
167
183
  ```
168
184
 
169
185
  诊断命令保持只读;`ip status` 这类依赖 VM/userspace 工具的命令会分别标记每个 probe 的 `ok/output/error`,工具缺失时输出 `partial_failure=true`,不会吞掉其它已成功字段。
@@ -187,17 +203,16 @@ fh-tool backup verify backup.tgz
187
203
  `restore` 默认只做 dry-run:解析 backup、验证 manifest/sha256,并显示将恢复的文件、目标路径和风险等级,不写入任何文件。
188
204
 
189
205
  ```bash
190
- fh-tool restore backup.tgz --dry-run
191
- fh-tool restore backup.tgz --dry-run --path /fhconf/usrconfig_conf
206
+ fh-tool restore backup.tgz
207
+ fh-tool restore backup.tgz --path /fhconf/usrconfig_conf
192
208
  ```
193
209
 
194
- 执行恢复必须显式指定本地目标根目录,并通过 extreme 风险确认:
210
+ 执行恢复必须显式指定本地目标根目录,并加 `--confirm`:
195
211
 
196
212
  ```bash
197
213
  fh-tool restore backup.tgz \
198
214
  --target-root /tmp/fh-tool-restore-root \
199
- --execute \
200
- --yes --danger --i-know-this-can-break-my-device
215
+ --confirm
201
216
  ```
202
217
 
203
218
  也可以选择真实设备目标。该模式会通过 Telnet 把 allowlist 文件先写入 `/tmp/fh-tool-restore` staging,远端 sha256 校验通过后才覆盖目标路径;仍然不会自动 reboot 或 factory reset:
@@ -206,8 +221,7 @@ fh-tool restore backup.tgz \
206
221
  fh-tool restore backup.tgz \
207
222
  --target device \
208
223
  --path /fhconf/usrconfig_conf \
209
- --execute \
210
- --yes --danger --i-know-this-can-break-my-device
224
+ --confirm
211
225
  ```
212
226
 
213
227
  当前 restore 只恢复 allowlist 内的配置文件,且会拒绝路径穿越、绝对路径逃逸和未知文件写入。`/proc/mtd`、runtime password 文件、restore/factory reset flag 等备份内容不会被恢复。恢复后会 read-back/hash verify;不会自动 reboot,也不会自动 factory reset。
@@ -222,12 +236,10 @@ fh-tool cloud audit --output cloud-report.md
222
236
  fh-tool cloud plan
223
237
  ```
224
238
 
225
- `cloud status/audit/plan` 会结构化显示 SmartSwitch 当前值、配置路径、禁用值、影响面和禁止改动项。禁用 SmartSwitch 只会写入 `InternetGatewayDevice.X_CT-COM_SmartSwitch.Enable=0`,需要先完成备份,并在写入后 read-back verify:
239
+ `cloud status/audit/plan` 会结构化显示 SmartSwitch 当前值、配置路径、禁用值、影响面和禁止改动项。禁用 SmartSwitch 只会写入 `InternetGatewayDevice.X_CT-COM_SmartSwitch.Enable=0`,不加 `--confirm` 只输出 dry-run 计划;确认写入后会 read-back verify:
226
240
 
227
241
  ```bash
228
- fh-tool cloud disable-smartswitch \
229
- --backup-confirmed \
230
- --yes --danger
242
+ fh-tool cloud disable-smartswitch --confirm
231
243
  ```
232
244
 
233
245
  该命令不会修改 LOID、PON、WAN VLAN、ServiceList 或 TR-069 VLAN。
@@ -239,33 +251,33 @@ fh-tool cloud disable-smartswitch \
239
251
  | func | command |
240
252
  |---|---|
241
253
  | `GetResult` | `fh-tool get-result` |
242
- | `SetResult` | `fh-tool set-result --result VALUE --yes` |
254
+ | `SetResult` | `fh-tool set-result --result VALUE [--confirm]` |
243
255
  | `GetPortMirror` | `fh-tool get-port-mirror` |
244
- | `SetPortMirror` | `fh-tool set-port-mirror --enable ... --direction ... --srcport ... --dstport ... --yes` |
256
+ | `SetPortMirror` | `fh-tool set-port-mirror --enable ... --direction ... --srcport ... --dstport ... [--confirm]` |
245
257
  | `LogDownload` | `fh-tool log-download [--output log.tar.gz]` |
246
258
  | `GetDevInfo` | `fh-tool dev-info` |
247
259
  | `GetAdminAccount` | `fh-tool admin-account` |
248
260
  | `GetRegAccount` | `fh-tool reg-account` |
249
- | `SetRegAccount` | `fh-tool set-reg-account --regname ... --regpwd ... --yes` |
261
+ | `SetRegAccount` | `fh-tool set-reg-account --regname ... --regpwd ... [--confirm]` |
250
262
  | `GetPwdRegPassword` | `fh-tool pwd-reg-password` |
251
- | `SetPwdRegPassword` | `fh-tool set-pwd-reg-password --password ... --yes` |
252
- | `DownloadFile` | `fh-tool download-file --file-name /var/... --output out.tar.gz --yes` |
253
- | `RestoreDefaultSettings` | `fh-tool restore-default-settings --yes --danger --i-know-this-can-break-my-device` |
263
+ | `SetPwdRegPassword` | `fh-tool set-pwd-reg-password --password ... [--confirm]` |
264
+ | `DownloadFile` | `fh-tool download-file --file-name /var/... --output out.tar.gz [--confirm]` |
265
+ | `RestoreDefaultSettings` | `fh-tool restore-default-settings [--confirm]` |
254
266
  | `UploadPrepare` | `fh-tool upload-prepare` |
255
- | `DeviceReboot` | `fh-tool reboot --yes --danger --i-know-this-can-break-my-device` |
267
+ | `DeviceReboot` | `fh-tool reboot [--confirm]` |
256
268
  | `GetPreconfig` | `fh-tool get-preconfig` |
257
- | `SetPreconfig` | `fh-tool set-preconfig --fullname ... --yes --danger` |
258
- | `TelnetEnable` | `fh-tool telnet enable --yes` / `fh-tool telnet disable --yes --danger` |
269
+ | `SetPreconfig` | `fh-tool set-preconfig --fullname ... [--confirm]` |
270
+ | `TelnetEnable` | `fh-tool telnet enable [--confirm]` / `fh-tool telnet disable [--confirm]` |
259
271
  | `GetPppoeAccount` | `fh-tool pppoe-account` |
260
- | `SetFHDebugLog` | `fh-tool set-fh-debug-log --module tr069 --data ... --yes --danger` |
261
- | `CloseFHDebugLog` | `fh-tool close-fh-debug-log --yes` |
262
- | `OpenFHDebugLog` | `fh-tool open-fh-debug-log --yes` |
272
+ | `SetFHDebugLog` | `fh-tool set-fh-debug-log --module tr069 --data ... [--confirm]` |
273
+ | `CloseFHDebugLog` | `fh-tool close-fh-debug-log [--confirm]` |
274
+ | `OpenFHDebugLog` | `fh-tool open-fh-debug-log [--confirm]` |
263
275
 
264
276
  原始调用入口:
265
277
 
266
278
  ```bash
267
279
  fh-tool call --func GetDevInfo
268
- fh-tool call --func TelnetEnable --param telnet=1 --allow-risky
280
+ fh-tool call --func TelnetEnable --param telnet=1 --confirm
269
281
  ```
270
282
 
271
283
  ## upload / download endpoint
@@ -284,10 +296,10 @@ fh-tool upload-prepare
284
296
  fh-tool upload-prepare --reveal-secrets
285
297
  ```
286
298
 
287
- 上传 firmware/preconfig 前先 dry-run:
299
+ 上传 firmware/preconfig 默认先 dry-run:
288
300
 
289
301
  ```bash
290
- fh-tool upload --action preconfig --file sysinfo_conf --sessionid TOKEN --dry-run
302
+ fh-tool upload --action preconfig --file sysinfo_conf --sessionid TOKEN
291
303
  ```
292
304
 
293
305
  真正上传属于 extreme 风险,只上传文件到 staging path,不会自动 reboot、restore 或切换 preconfig:
@@ -297,21 +309,22 @@ fh-tool upload \
297
309
  --action preconfig \
298
310
  --file sysinfo_conf \
299
311
  --sessionid TOKEN \
300
- --yes --danger --i-know-this-can-break-my-device
312
+ --confirm
301
313
  ```
302
314
 
303
315
  ## 风险边界
304
316
 
305
- 这些命令默认不会执行,必须显式确认:
317
+ 写入型命令默认不会执行,只输出 dry-run 计划和提示。确认执行只使用一个参数:
318
+
319
+ - `--confirm`: 执行写入、上传、恢复、重启等会改变设备状态的动作。
320
+ - `--reveal-secrets`: 只控制敏感字段是否明文输出,不代表写入确认。
306
321
 
307
- - `--yes`: 会写设备状态或创建下载文件。
308
- - `--danger`: 高风险写入、关闭 Telnet、执行 debug script。
309
- - `--i-know-this-can-break-my-device`: restore、firmware/preconfig upload、恢复出厂或重启。
322
+ 旧确认参数 `--yes`、`--danger`、`--backup-confirmed`、`--execute`、`--dry-run`、`--allow-risky` 和 `--i-know-this-can-break-my-device` 已弃用,传入会直接报错。
310
323
 
311
324
  当前设备如果需要保持 Telnet 打开,不要运行:
312
325
 
313
326
  ```bash
314
- fh-tool telnet disable --yes --danger
327
+ fh-tool telnet disable --confirm
315
328
  ```
316
329
 
317
330
  ## License
@@ -24,6 +24,18 @@ uv run fh-tool --help
24
24
 
25
25
  下文示例中的 `fh-tool ...` 如果是在源码目录内运行,可以统一写成 `uv run fh-tool ...`。
26
26
 
27
+ ## CLI 输出和日志
28
+
29
+ CLI 入口使用 Click,错误和日志输出使用 Rich。命令结果只写 stdout;错误、警告和日志写 stderr,便于脚本把 stdout 当作数据流处理。
30
+
31
+ ```bash
32
+ fh-tool --verbose probe --json
33
+ fh-tool --quiet config show
34
+ fh-tool --log-file fh-tool.log dev-info
35
+ ```
36
+
37
+ `--json` 输出稳定的 machine-readable JSON,不混入日志或样式。当前默认人类输出仍保持 pretty JSON,以兼容已有脚本;后续可以在不影响 `--json` 的前提下逐步增加表格化输出。
38
+
27
39
  ## 快速配置
28
40
 
29
41
  保存默认 IP/MAC:
@@ -89,7 +101,8 @@ fh-tool credentials derive --kind hg5143f-telnet --mac AABBCCDDEEFF
89
101
  打开 runtime Telnet:
90
102
 
91
103
  ```bash
92
- fh-tool telnet enable --yes
104
+ fh-tool telnet enable
105
+ fh-tool telnet enable --confirm
93
106
  ```
94
107
 
95
108
  检查端口:
@@ -120,7 +133,7 @@ fh-tool wan list --backend local-vm
120
133
 
121
134
  `local-vm` 只是在本机 proot VM 内执行厂商 `cfg_cmd`。`--vm-root` 必须指向 VM 工作区目录,也就是包含 `bin/proot-shell` 和 `rootfs-vm/fhrom/bin/cfg_cmd` 的目录;默认是 `/mnt/dev-cold/HG5143F-ONU-vm`。不要把它指到里面的 `rootfs-vm/`。
122
135
 
123
- Web AJAX 读取命令只读。需要复用已有 Web session 时加 `--sessionid`;需要登录时可显式传 `--password-stdin` 或 `--password`。未显式提供密码时默认 `--username useradmin --password-source auto`,会依次尝试 `GetAdminAccount` 和 cfg 路径读取 Web superadmin 密码;失败不会阻塞只读抓取。sessionid、密码、LOID、PPPoE 等敏感字段默认会脱敏;只有显式加 `--reveal-secrets` 才输出明文。
136
+ Web AJAX 读取命令只读。需要复用已有 Web session 时加 `--sessionid`;需要登录时可显式传 `--password-stdin` 或 `--password`。未显式提供密码时默认 `--username useradmin --password-source auto`,会依次尝试 `GetAdminAccount` 和 cfg 路径读取 Web superadmin 密码;cfg 来源需要 Telnet 时会默认使用 HG5143F 派生 Telnet 凭据 fallback,可用 `--no-derived-credentials` 关闭。失败不会阻塞只读抓取。sessionid、密码、LOID、PPPoE 等敏感字段默认会脱敏;只有显式加 `--reveal-secrets` 才输出明文。
124
137
 
125
138
  后台 AJAX 接口发现以 live discovery 为主路径,不需要 HAR,也不需要 rootfs:
126
139
 
@@ -132,24 +145,25 @@ fh-tool web discover merge --input web-ajax-catalog.json --input static-web-ajax
132
145
 
133
146
  `live` 只探测只读 `get_*/query_*/show_*` 候选;写候选只进入 catalog,不会自动 POST。`static` 是补充路径,用于从 rootfs/备份目录扫描 HTML/JS/CSS 里的 `ajaxmethod`、参数名和上下文。
134
147
 
135
- Web AJAX 写接口默认只做 dry-run。执行 POST 需要先完成备份,并显式加 `--execute --backup-confirmed --yes --danger`:
148
+ Web AJAX 写接口默认只做 dry-run,并会提示重新运行时加 `--confirm` 才会执行 POST:
136
149
 
137
150
  ```bash
138
151
  fh-tool web ajax post set_wan_info --param VLANID=100
139
152
  fh-tool web ajax replay --catalog web-ajax-catalog.json --method set_wan_info --param VLANID=100
140
153
  fh-tool web port-mapping set --operation add --wan-index 1 --wan-session-index 1 --wan-iporppp ppp --external-port 8080 --protocol tcp --internal-client 192.168.1.2 --internal-port 80
141
154
  fh-tool web vlanbind set --operation add --if-name eth1 --user-vlan 100 --wan-vlan 100
142
- fh-tool web firewall set --enable 1 --level medium --dos-enable 1 --ipv6-enable 1 --execute --backup-confirmed --yes --danger
143
- fh-tool web services set --service telnet --enabled 0 --execute --backup-confirmed --yes --danger
155
+ fh-tool web firewall set --enable 1 --level medium --dos-enable 1 --ipv6-enable 1 --confirm
156
+ fh-tool web services set --service telnet --enabled 0 --confirm
144
157
  ```
145
158
 
146
- 常规 Web 写接口优先使用 typed 参数。`web ajax post` 和 `web ajax replay` 支持任意已知或未知 AJAX method,默认只输出计划,不发 POST;执行同样必须加 `--execute --backup-confirmed --yes --danger`,且默认拒绝空 payload。`--json-payload` 和可重复的 `--param k=v` 仍保留为固件差异逃生口,合并顺序是 typed 参数、JSON、最后 `--param` 覆盖。
159
+ 常规 Web 写接口优先使用 typed 参数。`web ajax post` 和 `web ajax replay` 支持任意已知或未知 AJAX method,默认只输出计划,不发 POST;执行必须加 `--confirm`,且默认拒绝空 payload。`--json-payload` 和可重复的 `--param k=v` 仍保留为固件差异逃生口,合并顺序是 typed 参数、JSON、最后 `--param` 覆盖。旧的确认参数会直接报弃用错误。
147
160
 
148
- Telnet/cfg/诊断命令默认不会自动套用派生凭据。如果设备仍是 HG5143F 默认 Telnet 规则,并且已提供或保存 MAC,可以显式加 `--use-derived-credentials` 作为 fallback:
161
+ Telnet/cfg/诊断命令在未显式传 Telnet 密码时,会默认使用 HG5143F 派生 Telnet 凭据 fallback;显式传入的用户名/密码始终优先。如果设备不是该规则,或需要保留空凭据/自定义认证,可加 `--no-derived-credentials` 关闭。`--use-derived-credentials` 仍作为兼容参数接受:
149
162
 
150
163
  ```bash
151
- fh-tool cfg get InternetGatewayDevice.DeviceInfo.Manufacturer --use-derived-credentials
152
- fh-tool wan list --use-derived-credentials
164
+ fh-tool cfg get InternetGatewayDevice.DeviceInfo.Manufacturer
165
+ fh-tool wan list
166
+ fh-tool cfg get InternetGatewayDevice.DeviceInfo.Manufacturer --no-derived-credentials
153
167
  ```
154
168
 
155
169
  诊断命令保持只读;`ip status` 这类依赖 VM/userspace 工具的命令会分别标记每个 probe 的 `ok/output/error`,工具缺失时输出 `partial_failure=true`,不会吞掉其它已成功字段。
@@ -173,17 +187,16 @@ fh-tool backup verify backup.tgz
173
187
  `restore` 默认只做 dry-run:解析 backup、验证 manifest/sha256,并显示将恢复的文件、目标路径和风险等级,不写入任何文件。
174
188
 
175
189
  ```bash
176
- fh-tool restore backup.tgz --dry-run
177
- fh-tool restore backup.tgz --dry-run --path /fhconf/usrconfig_conf
190
+ fh-tool restore backup.tgz
191
+ fh-tool restore backup.tgz --path /fhconf/usrconfig_conf
178
192
  ```
179
193
 
180
- 执行恢复必须显式指定本地目标根目录,并通过 extreme 风险确认:
194
+ 执行恢复必须显式指定本地目标根目录,并加 `--confirm`:
181
195
 
182
196
  ```bash
183
197
  fh-tool restore backup.tgz \
184
198
  --target-root /tmp/fh-tool-restore-root \
185
- --execute \
186
- --yes --danger --i-know-this-can-break-my-device
199
+ --confirm
187
200
  ```
188
201
 
189
202
  也可以选择真实设备目标。该模式会通过 Telnet 把 allowlist 文件先写入 `/tmp/fh-tool-restore` staging,远端 sha256 校验通过后才覆盖目标路径;仍然不会自动 reboot 或 factory reset:
@@ -192,8 +205,7 @@ fh-tool restore backup.tgz \
192
205
  fh-tool restore backup.tgz \
193
206
  --target device \
194
207
  --path /fhconf/usrconfig_conf \
195
- --execute \
196
- --yes --danger --i-know-this-can-break-my-device
208
+ --confirm
197
209
  ```
198
210
 
199
211
  当前 restore 只恢复 allowlist 内的配置文件,且会拒绝路径穿越、绝对路径逃逸和未知文件写入。`/proc/mtd`、runtime password 文件、restore/factory reset flag 等备份内容不会被恢复。恢复后会 read-back/hash verify;不会自动 reboot,也不会自动 factory reset。
@@ -208,12 +220,10 @@ fh-tool cloud audit --output cloud-report.md
208
220
  fh-tool cloud plan
209
221
  ```
210
222
 
211
- `cloud status/audit/plan` 会结构化显示 SmartSwitch 当前值、配置路径、禁用值、影响面和禁止改动项。禁用 SmartSwitch 只会写入 `InternetGatewayDevice.X_CT-COM_SmartSwitch.Enable=0`,需要先完成备份,并在写入后 read-back verify:
223
+ `cloud status/audit/plan` 会结构化显示 SmartSwitch 当前值、配置路径、禁用值、影响面和禁止改动项。禁用 SmartSwitch 只会写入 `InternetGatewayDevice.X_CT-COM_SmartSwitch.Enable=0`,不加 `--confirm` 只输出 dry-run 计划;确认写入后会 read-back verify:
212
224
 
213
225
  ```bash
214
- fh-tool cloud disable-smartswitch \
215
- --backup-confirmed \
216
- --yes --danger
226
+ fh-tool cloud disable-smartswitch --confirm
217
227
  ```
218
228
 
219
229
  该命令不会修改 LOID、PON、WAN VLAN、ServiceList 或 TR-069 VLAN。
@@ -225,33 +235,33 @@ fh-tool cloud disable-smartswitch \
225
235
  | func | command |
226
236
  |---|---|
227
237
  | `GetResult` | `fh-tool get-result` |
228
- | `SetResult` | `fh-tool set-result --result VALUE --yes` |
238
+ | `SetResult` | `fh-tool set-result --result VALUE [--confirm]` |
229
239
  | `GetPortMirror` | `fh-tool get-port-mirror` |
230
- | `SetPortMirror` | `fh-tool set-port-mirror --enable ... --direction ... --srcport ... --dstport ... --yes` |
240
+ | `SetPortMirror` | `fh-tool set-port-mirror --enable ... --direction ... --srcport ... --dstport ... [--confirm]` |
231
241
  | `LogDownload` | `fh-tool log-download [--output log.tar.gz]` |
232
242
  | `GetDevInfo` | `fh-tool dev-info` |
233
243
  | `GetAdminAccount` | `fh-tool admin-account` |
234
244
  | `GetRegAccount` | `fh-tool reg-account` |
235
- | `SetRegAccount` | `fh-tool set-reg-account --regname ... --regpwd ... --yes` |
245
+ | `SetRegAccount` | `fh-tool set-reg-account --regname ... --regpwd ... [--confirm]` |
236
246
  | `GetPwdRegPassword` | `fh-tool pwd-reg-password` |
237
- | `SetPwdRegPassword` | `fh-tool set-pwd-reg-password --password ... --yes` |
238
- | `DownloadFile` | `fh-tool download-file --file-name /var/... --output out.tar.gz --yes` |
239
- | `RestoreDefaultSettings` | `fh-tool restore-default-settings --yes --danger --i-know-this-can-break-my-device` |
247
+ | `SetPwdRegPassword` | `fh-tool set-pwd-reg-password --password ... [--confirm]` |
248
+ | `DownloadFile` | `fh-tool download-file --file-name /var/... --output out.tar.gz [--confirm]` |
249
+ | `RestoreDefaultSettings` | `fh-tool restore-default-settings [--confirm]` |
240
250
  | `UploadPrepare` | `fh-tool upload-prepare` |
241
- | `DeviceReboot` | `fh-tool reboot --yes --danger --i-know-this-can-break-my-device` |
251
+ | `DeviceReboot` | `fh-tool reboot [--confirm]` |
242
252
  | `GetPreconfig` | `fh-tool get-preconfig` |
243
- | `SetPreconfig` | `fh-tool set-preconfig --fullname ... --yes --danger` |
244
- | `TelnetEnable` | `fh-tool telnet enable --yes` / `fh-tool telnet disable --yes --danger` |
253
+ | `SetPreconfig` | `fh-tool set-preconfig --fullname ... [--confirm]` |
254
+ | `TelnetEnable` | `fh-tool telnet enable [--confirm]` / `fh-tool telnet disable [--confirm]` |
245
255
  | `GetPppoeAccount` | `fh-tool pppoe-account` |
246
- | `SetFHDebugLog` | `fh-tool set-fh-debug-log --module tr069 --data ... --yes --danger` |
247
- | `CloseFHDebugLog` | `fh-tool close-fh-debug-log --yes` |
248
- | `OpenFHDebugLog` | `fh-tool open-fh-debug-log --yes` |
256
+ | `SetFHDebugLog` | `fh-tool set-fh-debug-log --module tr069 --data ... [--confirm]` |
257
+ | `CloseFHDebugLog` | `fh-tool close-fh-debug-log [--confirm]` |
258
+ | `OpenFHDebugLog` | `fh-tool open-fh-debug-log [--confirm]` |
249
259
 
250
260
  原始调用入口:
251
261
 
252
262
  ```bash
253
263
  fh-tool call --func GetDevInfo
254
- fh-tool call --func TelnetEnable --param telnet=1 --allow-risky
264
+ fh-tool call --func TelnetEnable --param telnet=1 --confirm
255
265
  ```
256
266
 
257
267
  ## upload / download endpoint
@@ -270,10 +280,10 @@ fh-tool upload-prepare
270
280
  fh-tool upload-prepare --reveal-secrets
271
281
  ```
272
282
 
273
- 上传 firmware/preconfig 前先 dry-run:
283
+ 上传 firmware/preconfig 默认先 dry-run:
274
284
 
275
285
  ```bash
276
- fh-tool upload --action preconfig --file sysinfo_conf --sessionid TOKEN --dry-run
286
+ fh-tool upload --action preconfig --file sysinfo_conf --sessionid TOKEN
277
287
  ```
278
288
 
279
289
  真正上传属于 extreme 风险,只上传文件到 staging path,不会自动 reboot、restore 或切换 preconfig:
@@ -283,21 +293,22 @@ fh-tool upload \
283
293
  --action preconfig \
284
294
  --file sysinfo_conf \
285
295
  --sessionid TOKEN \
286
- --yes --danger --i-know-this-can-break-my-device
296
+ --confirm
287
297
  ```
288
298
 
289
299
  ## 风险边界
290
300
 
291
- 这些命令默认不会执行,必须显式确认:
301
+ 写入型命令默认不会执行,只输出 dry-run 计划和提示。确认执行只使用一个参数:
302
+
303
+ - `--confirm`: 执行写入、上传、恢复、重启等会改变设备状态的动作。
304
+ - `--reveal-secrets`: 只控制敏感字段是否明文输出,不代表写入确认。
292
305
 
293
- - `--yes`: 会写设备状态或创建下载文件。
294
- - `--danger`: 高风险写入、关闭 Telnet、执行 debug script。
295
- - `--i-know-this-can-break-my-device`: restore、firmware/preconfig upload、恢复出厂或重启。
306
+ 旧确认参数 `--yes`、`--danger`、`--backup-confirmed`、`--execute`、`--dry-run`、`--allow-risky` 和 `--i-know-this-can-break-my-device` 已弃用,传入会直接报错。
296
307
 
297
308
  当前设备如果需要保持 Telnet 打开,不要运行:
298
309
 
299
310
  ```bash
300
- fh-tool telnet disable --yes --danger
311
+ fh-tool telnet disable --confirm
301
312
  ```
302
313
 
303
314
  ## License
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fh_tool-cli"
7
- version = "0.2.0"
7
+ version = "0.2.2"
8
8
  description = "用于本地管理 FiberHome fh_tool 接口的 Python CLI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -18,8 +18,10 @@ classifiers = [
18
18
  "Topic :: System :: Networking",
19
19
  ]
20
20
  dependencies = [
21
+ "click>=8.1.0",
21
22
  "cryptography>=42.0.0",
22
23
  "requests>=2.31.0",
24
+ "rich>=13.7.0",
23
25
  ]
24
26
 
25
27
  [project.scripts]
@@ -1,3 +1,3 @@
1
1
  """Local CLI for FiberHome fh_tool endpoints."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.1"
@@ -341,7 +341,7 @@ def restore_backup_archive(
341
341
  allowlist: list[str] | None = None,
342
342
  ) -> dict[str, Any]:
343
343
  if not dry_run and target_root is None:
344
- raise CliError("restore --execute 需要显式指定 --target-root")
344
+ raise CliError("restore --confirm 需要显式指定 --target-root")
345
345
 
346
346
  allowed = set(allowlist or RESTORE_ALLOWLIST)
347
347
  requested = {_normalize_device_path(path) for path in paths or []}