Skip to main content

pswitch

把多个上游代理聚合到一个固定本地端口(默认 127.0.0.1:17000)。 客户端只认这个端口,切换上游只需一条命令,不再改环境变量。

                  ┌──────────────────────┐
 curl/git/npm ───▶│ 127.0.0.1:17000      │
 浏览器/GUI   ───▶│ pswitch (TCP 转发)    │───▶ upstream A
                  │                      │───▶ upstream B
                  └──────────────────────┘───▶ upstream C

安装

uv tool install pswitch
# 或者
pip install pswitch

升级:

uv tool upgrade pswitch
# 或者
pip install -U pswitch

从源码安装(开发用):

git clone https://github.com/WalterYOO/pswitch.git
uv tool install ./pswitch

安装后可执行文件位于 ~/.local/bin/pswitch,确认该目录在 PATH 中:

command -v pswitch

Rust 版(高吞吐 / 低延迟)

仓库内还有一份功能等价的 Rust 实现,配置与状态文件格式完全兼容:

cargo build --release --manifest-path rust/Cargo.toml
install -m 755 rust/target/release/pswitch ~/.local/bin/pswitch

构建方式、设计要点和与 Python 版的基准对照见 rust/README.md。

首次运行

代码里不内置任何上游。第一次执行任意命令时会自动创建配置文件, 其中 upstreams 为空:

pswitch status
# 已创建配置文件: ~/.config/proxy_switch/config.json(还没有上游,用 pswitch add 添加)

添加上游后才能启动:

pswitch add local  127.0.0.1:17890
pswitch add office 192.168.212.21:17090
pswitch start

没有配置任何上游时,pswitch start 和 pswitch install 会拒绝执行并返回退出码 1。

日常使用

pswitch status          # 当前走哪个、各上游实时探活
pswitch use office      # 固定走某一个
pswitch use auto        # 自动:按优先级顺序选第一个真正能通的(推荐)
pswitch use direct      # 全部直连:不经过任何上游
pswitch priority        # 查看优先级顺序
pswitch priority office 1   # 把 office 提到最高优先级
pswitch list            # 列出全部上游
pswitch test            # 经本地端口发真实请求验证
pswitch env             # 打印代理环境变量
pswitch system on       # 系统代理 -> 本地端口 127.0.0.1:17000
pswitch system use office    # 系统代理 -> 直接指向 office 的地址(不经过 pswitch)
pswitch system use 10.0.0.8:8080   # 也可以直接给 host:port
pswitch disable office  # 临时不用它(如内网代理在当前网络不可达),配置保留
pswitch enable office   # 恢复
pswitch version         # 查看当前版本号

命令

命令 作用
start / stop / restart 管理守护进程
status 进程、监听、当前上游、各上游实时探活结果
use <名字|auto|direct> 切换出口(auto = 自动选择;direct = 不经上游直接连目标)
list / add <名> <host:port> / remove <名> 管理上游列表
enable <名> / disable <名> 临时启用/禁用某个上游:配置保留,禁用后不参与 use、auto 选路和故障转移
priority [<名> [位置]] 查看优先级顺序;给出名字和位置则把该上游移到该位置(1 = 最高)
env 打印代理环境变量
test 经本地端口请求 gstatic 的 204 接口
logs [-n 行数] 查看日志(~/.config/proxy_switch/pswitch.log)
install / uninstall 安装/卸载 launchd 开机自启
system on|off|status 把 macOS 系统代理指向/取消指向本地端口
system use <名|host:port> 把系统代理直接指向某个上游(不经过 pswitch;system on 可切回本地端口)
version(或 -V / --version) 查看版本号

配置文件

~/.config/proxy_switch/config.json(PSWITCH_HOME 可覆盖目录):

{
  "listen": "127.0.0.1:17000",
  "mode": "auto",
  "active": null,
  "health_check_interval": 10,
  "connect_timeout": 3,
  "failover": true,
  "probe_url": "http://connectivitycheck.gstatic.com/generate_204",
  "probe_timeout": 3,
  "upstreams": []
}
  • 直接编辑也没关系,守护进程会检测到文件变化并自动重载。
  • 改 listen 需要 pswitch restart 才生效。
  • mode: auto 时按 upstreams 顺序取第一个探活通过的;mode: manual 时固定 active。
  • mode: direct 时完全不使用上游:pswitch 自己解析 HTTP CONNECT / 普通 HTTP / SOCKS5, 直接连接目标。此时没有配置上游也能 pswitch start,use direct 与 use auto|名字 可随时互切,客户端的环境变量和系统代理指向都不用改。
  • upstreams 的数组顺序就是优先级:先比探活等级(HTTP 通 > 只通 TCP),同级按顺序取第一个, 不看延迟。pswitch add 追加到末尾(最低),pswitch priority <名> <位置> 调整, list / priority 里的编号就是选路顺序。
  • 每个上游可带 "enabled": false(pswitch disable <名> 会写入)。禁用的上游保留在配置里, 但探活、auto 选路、故障转移都会跳过它;如果 mode: manual 的 active 正好被禁用, 选路会当作没命中,退回 auto 顺序。pswitch enable <名> 即可恢复。
  • 全部上游都被禁用时,pswitch start 会拒绝启动,系统代理也不会被打开。
  • 探活地址可以换成内网地址,避免依赖外网:例如 "probe_url": "http://your-intranet/health"(要求返回 200/204)。

与 shell 环境变量的关系

如果环境变量由 zsh-osx-autoproxy 之类的插件从 macOS 系统代理设置导出, 让系统代理指向本地端口即可,新终端会自动跟随:

pswitch install        # 开机自启,挂了自动拉起
pswitch system on      # 系统代理 -> 127.0.0.1:17000

GUI 应用也一起生效。恢复直连或换回原来的代理:pswitch system off。

如果只想影响命令行,把 pswitch env 的输出追加到 ~/.zshrc 末尾 (放在 oh-my-zsh 加载之后,才能覆盖插件设置)。

工作方式

  • 在 TCP 层透明转发,同一个本地端口既能当 HTTP 代理,也能当 SOCKS5 代理。
  • 每 health_check_interval 秒对每个上游做一次真实 HTTP 探活;只通 TCP 但转发失败 (例如返回 502)的上游会被标记为 TCP only,自动选路时排在后面。
  • 当前上游临时连不上时,单条连接会自动借用其它可用上游。
  • direct 模式下 pswitch 自己充当代理:支持 HTTP CONNECT、普通 HTTP(首个请求改写为 origin-form 并强制 Connection: close)和无认证 SOCKS5 CONNECT;BIND / UDP ASSOCIATE 和 SOCKS4 不支持,会明确拒绝。

Go 实现

go/ 下有一份功能完全对齐的 Go 重写,面向高吞吐、低延迟场景:

cd go
go build -o bin/pswitch ./cmd/pswitch
./bin/pswitch version

配置目录、state.json、PID、日志格式和全部 CLI 命令都与 Python 版一致, 可直接替换二进制。设计说明与同机基准对比见 go/README.md。

性能测试

bench/ 下有一套可重复的延迟与转发吞吐基准。 每次运行使用独立的临时 PSWITCH_HOME 和 171xx 端口, 不会影响正在运行的 127.0.0.1:17000:

python bench/bench.py all

# 测其它实现(需先按各自的 README 构建)
python bench/bench.py all --impl go
python bench/bench.py all --impl rust

结果写入 bench/results/<时间戳>/SUMMARY.md。 测量口径见 bench/PLAN.md(延迟)与 bench/THROUGHPUT-PLAN.md(吞吐), 用法与基线结果见 bench/README.md, 三份实现的横向对比见 bench/COMPARISON.md。

更新记录

见 CHANGELOG.md。

注意事项

  • 系统代理指向本地端口后,pswitch 停掉就等于断网。建议先 install 再 system on。
  • pswitch system use 会让系统代理直接连上游,绕过本地转发:此时 pswitch use、 auto 选路和故障转移都不生效,上游挂了就直接断网。切回本地端口用 pswitch system on。
  • 手动 use <名字> 的语义是“钉死”;要自动避开坏上游就用 use auto。
  • no_proxy 里保留 127.0.0.1,localhost,否则访问本地服务可能被绕一圈。
  • 从源码目录执行 python -m pswitch 时,注意不要与旧版的 pswitch.py 同名冲突; 正常使用安装后的 pswitch 命令即可。

Metadata

Release files for pswitch 0.1.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pswitch 0.1.6
File Size Uploaded Provenance
pswitch-0.1.6.tar.gz 29.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pswitch 0.1.6
File Interpreter ABI Platform
pswitch-0.1.6-py3-none-any.whl Python 3 none any Details

Total release size: 54.5 kB

Release files / pswitch-0.1.6.tar.gz

Download URL pswitch-0.1.6.tar.gz
Size 29.3 kB
Tags Source
SHA-256 checksum
How to use checksums
cccb5659e2e412b3f3cb5e84b89e0db725607487dc96c44489d903dfe2c754ad
BLAKE2b-256 checksum
How to use checksums
e715469c1d5f0e31d6c736e5b33cc6f27fd2dcce980cff31959372ef2ee10a01
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.11

Release files / pswitch-0.1.6-py3-none-any.whl

Download URL pswitch-0.1.6-py3-none-any.whl
Size 25.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
00f3e6e885a2d8e35c14356726e4c22852afc2b2c78a12e5ed98bbebc25a7e7a
BLAKE2b-256 checksum
How to use checksums
d7b2be5fc9542ba126f6fca5ffa075b83081b4b103753e33c5c1deff49f2a21c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.11

Security for pswitch 0.1.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.6 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page