proxyctl 0.1.1__tar.gz → 0.1.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.
- {proxyctl-0.1.1 → proxyctl-0.1.3}/PKG-INFO +7 -1
- {proxyctl-0.1.1 → proxyctl-0.1.3}/README.md +4 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/pyproject.toml +3 -1
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/__init__.py +1 -1
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/cli.py +51 -10
- {proxyctl-0.1.1 → proxyctl-0.1.3}/.gitignore +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/LICENSE +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/audit.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/builtin_plugins/__init__.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/builtin_plugins/connectivity_basic.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/builtin_plugins/corp_network.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/check.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/core/__init__.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/core/plugin.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/engine/__init__.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/engine/base.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/engine/mihomo.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/engine/singbox.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/status.py +0 -0
- {proxyctl-0.1.1 → proxyctl-0.1.3}/src/proxyctl/trace.py +0 -0
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: proxyctl
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Proxy configuration lifecycle management for macOS and Linux
|
|
5
5
|
Project-URL: Homepage, https://github.com/crhan/proxyctl
|
|
6
6
|
Project-URL: Issues, https://github.com/crhan/proxyctl/issues
|
|
7
|
+
Project-URL: Changelog, https://github.com/crhan/proxyctl/blob/main/CHANGELOG.md
|
|
8
|
+
Project-URL: Repository, https://github.com/crhan/proxyctl
|
|
7
9
|
Author-email: crhan <crhan123@gmail.com>
|
|
8
10
|
License: MIT
|
|
9
11
|
License-File: LICENSE
|
|
@@ -225,6 +227,10 @@ python3 bin/proxyctl status
|
|
|
225
227
|
export PROXYCTL_DEBUG=1
|
|
226
228
|
```
|
|
227
229
|
|
|
230
|
+
## Changelog
|
|
231
|
+
|
|
232
|
+
版本变更记录见 [CHANGELOG.md](https://github.com/crhan/proxyctl/blob/main/CHANGELOG.md)。
|
|
233
|
+
|
|
228
234
|
## License
|
|
229
235
|
|
|
230
236
|
MIT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "proxyctl"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.3"
|
|
4
4
|
description = "Proxy configuration lifecycle management for macOS and Linux"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -27,6 +27,8 @@ dependencies = ["pyyaml>=6.0"]
|
|
|
27
27
|
[project.urls]
|
|
28
28
|
Homepage = "https://github.com/crhan/proxyctl"
|
|
29
29
|
Issues = "https://github.com/crhan/proxyctl/issues"
|
|
30
|
+
Changelog = "https://github.com/crhan/proxyctl/blob/main/CHANGELOG.md"
|
|
31
|
+
Repository = "https://github.com/crhan/proxyctl"
|
|
30
32
|
|
|
31
33
|
[project.scripts]
|
|
32
34
|
proxyctl = "proxyctl.cli:main"
|
|
@@ -518,9 +518,33 @@ def _wait_ready(backend: Backend):
|
|
|
518
518
|
time.sleep(3)
|
|
519
519
|
|
|
520
520
|
|
|
521
|
+
# ── 路由钩子调度 ──────────────────────────────────────────────────────────────
|
|
522
|
+
|
|
523
|
+
def _apply_route_hooks(registry, ctx: dict, action: str) -> None:
|
|
524
|
+
"""调度所有插件的 RouteHook。action ∈ {'activate', 'deactivate'}。
|
|
525
|
+
|
|
526
|
+
单个 hook 失败只打 warning,不中断主流程——路由注入是辅助优化,
|
|
527
|
+
不能让某个插件挂了拖死 start/stop。
|
|
528
|
+
"""
|
|
529
|
+
if registry is None:
|
|
530
|
+
return
|
|
531
|
+
hooks = registry.collect("route_hooks")
|
|
532
|
+
for h in hooks:
|
|
533
|
+
fn = getattr(h, action, None)
|
|
534
|
+
if fn is None:
|
|
535
|
+
continue
|
|
536
|
+
try:
|
|
537
|
+
fn(ctx)
|
|
538
|
+
except Exception as e:
|
|
539
|
+
sys.stderr.write(
|
|
540
|
+
f"[route_hook warning] {h.name}.{action} failed: "
|
|
541
|
+
f"{type(e).__name__}: {e}\n"
|
|
542
|
+
)
|
|
543
|
+
|
|
544
|
+
|
|
521
545
|
# ── 命令:start ───────────────────────────────────────────────────────────────
|
|
522
546
|
|
|
523
|
-
def cmd_start(backend: Backend, config: dict):
|
|
547
|
+
def cmd_start(backend: Backend, config: dict, registry=None):
|
|
524
548
|
r = service_start(backend, config)
|
|
525
549
|
if r.returncode != 0:
|
|
526
550
|
print(f"{RED}✗{NC} {backend.name} 启动失败")
|
|
@@ -538,10 +562,18 @@ def cmd_start(backend: Backend, config: dict):
|
|
|
538
562
|
proxy_activate()
|
|
539
563
|
print("系统代理 → 127.0.0.1:7890 (已激活)")
|
|
540
564
|
|
|
565
|
+
_apply_route_hooks(registry,
|
|
566
|
+
{"engine": backend.name, "config": config, "phase": "start"},
|
|
567
|
+
"activate")
|
|
568
|
+
|
|
541
569
|
|
|
542
570
|
# ── 命令:stop ────────────────────────────────────────────────────────────────
|
|
543
571
|
|
|
544
|
-
def cmd_stop(backend: Backend, config: dict):
|
|
572
|
+
def cmd_stop(backend: Backend, config: dict, registry=None):
|
|
573
|
+
_apply_route_hooks(registry,
|
|
574
|
+
{"engine": backend.name, "config": config, "phase": "stop"},
|
|
575
|
+
"deactivate")
|
|
576
|
+
|
|
545
577
|
if IS_MACOS:
|
|
546
578
|
dns_lock_stop(config)
|
|
547
579
|
dns_deactivate(config)
|
|
@@ -554,7 +586,7 @@ def cmd_stop(backend: Backend, config: dict):
|
|
|
554
586
|
|
|
555
587
|
# ── 命令:restart ─────────────────────────────────────────────────────────────
|
|
556
588
|
|
|
557
|
-
def cmd_restart(backend: Backend, config: dict, *, clean: bool = False):
|
|
589
|
+
def cmd_restart(backend: Backend, config: dict, *, clean: bool = False, registry=None):
|
|
558
590
|
if clean and os.path.isfile(backend.cache_file):
|
|
559
591
|
os.remove(backend.cache_file)
|
|
560
592
|
# 人工介入后清掉 watchdog 的失败状态,避免误判为"还在触顶窗口内"
|
|
@@ -578,10 +610,14 @@ def cmd_restart(backend: Backend, config: dict, *, clean: bool = False):
|
|
|
578
610
|
else:
|
|
579
611
|
proxy_deactivate()
|
|
580
612
|
|
|
613
|
+
_apply_route_hooks(registry,
|
|
614
|
+
{"engine": backend.name, "config": config, "phase": "restart"},
|
|
615
|
+
"activate")
|
|
616
|
+
|
|
581
617
|
|
|
582
618
|
# ── 命令:fix ─────────────────────────────────────────────────────────────────
|
|
583
619
|
|
|
584
|
-
def cmd_fix(backend: Backend, config: dict):
|
|
620
|
+
def cmd_fix(backend: Backend, config: dict, registry=None):
|
|
585
621
|
"""修复引擎状态:运行中则重注入 DNS/代理,已停止则还原系统配置。"""
|
|
586
622
|
api_base = config.get("api_base", DEFAULTS["api_base"])
|
|
587
623
|
api_secret = config.get("api_secret", "")
|
|
@@ -602,6 +638,11 @@ def cmd_fix(backend: Backend, config: dict):
|
|
|
602
638
|
if get_mode(backend) == "proxy":
|
|
603
639
|
proxy_activate()
|
|
604
640
|
print(f" {GREEN}✓{NC} 系统代理 → 127.0.0.1:7890")
|
|
641
|
+
|
|
642
|
+
_apply_route_hooks(registry,
|
|
643
|
+
{"engine": backend.name, "config": config,
|
|
644
|
+
"phase": "fix"},
|
|
645
|
+
"activate")
|
|
605
646
|
else:
|
|
606
647
|
print(f"{BOLD}[引擎运行中] 尝试热重载配置{NC}")
|
|
607
648
|
|
|
@@ -1176,7 +1217,7 @@ def cmd_env(config: dict, unset: bool = False):
|
|
|
1176
1217
|
|
|
1177
1218
|
# ── 帮助 ──────────────────────────────────────────────────────────────────────
|
|
1178
1219
|
|
|
1179
|
-
VERSION = "0.1.
|
|
1220
|
+
VERSION = "0.1.3"
|
|
1180
1221
|
|
|
1181
1222
|
def cmd_help(verbose: bool = False):
|
|
1182
1223
|
"""打印帮助信息
|
|
@@ -1280,13 +1321,13 @@ def main():
|
|
|
1280
1321
|
cmd = sys.argv[1] if len(sys.argv) > 1 else "status"
|
|
1281
1322
|
|
|
1282
1323
|
if cmd == "start":
|
|
1283
|
-
cmd_start(backend, config)
|
|
1324
|
+
cmd_start(backend, config, registry=registry)
|
|
1284
1325
|
elif cmd == "stop":
|
|
1285
|
-
cmd_stop(backend, config)
|
|
1326
|
+
cmd_stop(backend, config, registry=registry)
|
|
1286
1327
|
elif cmd == "restart":
|
|
1287
|
-
cmd_restart(backend, config)
|
|
1328
|
+
cmd_restart(backend, config, registry=registry)
|
|
1288
1329
|
elif cmd == "restart-clean":
|
|
1289
|
-
cmd_restart(backend, config, clean=True)
|
|
1330
|
+
cmd_restart(backend, config, clean=True, registry=registry)
|
|
1290
1331
|
elif cmd == "status":
|
|
1291
1332
|
from proxyctl.status import cmd_status
|
|
1292
1333
|
mode_str = get_mode(backend)
|
|
@@ -1303,7 +1344,7 @@ def main():
|
|
|
1303
1344
|
default_groups = registry.collect("check_groups") if registry else None
|
|
1304
1345
|
cmd_bench(api_base, api_secret, bench_groups, default_groups=default_groups)
|
|
1305
1346
|
elif cmd == "fix":
|
|
1306
|
-
cmd_fix(backend, config)
|
|
1347
|
+
cmd_fix(backend, config, registry=registry)
|
|
1307
1348
|
elif cmd == "recover":
|
|
1308
1349
|
cmd_recover(backend, config)
|
|
1309
1350
|
elif cmd == "dns-lock":
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|