再见 SwitchHosts!我写了个 1MB 的 Hosts 切换工具,还能跑在 CI/CD 里

再见 SwitchHosts!我写了个 1MB 的 Hosts 切换工具,还能跑在 CI/CD 里

Hostly封面图_融合图标版(1)

上周三下午,测试环境出了个诡异的 bug。

用户反馈订单状态不对,但我本地跑得好好的。没办法,只能连测试环境的数据库看看。打开 SwitchHosts,把 pig-mysql127.0.0.1 切到测试服务器的 IP,重启项目,复现问题,定位到是一个并发锁的问题。

修完 bug,提交代码,切回本地环境继续开发。

等等,我切回来了吗?

看一眼 SwitchHosts,当前激活的是… 我不确定。界面上显示的配置名太长,被截断了,看不清是”本地开发”还是”测试环境”。算了,跑一下代码试试——报错了,连不上数据库。

原来还在连测试环境。我忘了切回来。

这种事一周发生好几次。更让人崩溃的是,我瞄了一眼任务管理器:SwitchHosts 占了 300MB 内存。

一个 Hosts 切换工具,常驻 300MB。就为了帮我改几行 /etc/hosts

为什么开发者需要频繁切换 Hosts

先说清楚一个问题:为什么我们需要 Hosts 切换工具?

做 Java 开发的都知道,配置文件里不应该写死数据库、Redis、MQ 这些中间件的 IP 地址。为什么?因为你写死 192.168.1.100:3306,换个环境就得改代码。测试环境一套 IP,预发环境一套 IP,生产环境又是一套。每次部署都要改配置文件,改完还得重新打包,这不是给自己找麻烦吗?

正确的做法是用域名。配置文件里写 pig-mysql:3306pig-redis:6379pig-gateway:9999,然后通过 Hosts 文件或者 DNS 来解析这些域名。本地开发时,Hosts 把 pig-mysql 指向 127.0.0.1;部署到 K8s 集群时,这些域名自动解析到对应的 Service。

这就是容器化部署的精髓:host 就是 service name

在 Docker Compose 里,你定义一个 service 叫 pig-mysql,其他容器就可以直接用 pig-mysql 这个域名访问它。在 Kubernetes 里也一样,Service 的名字就是 DNS 名。你的代码不需要知道具体 IP 是多少,只需要知道”我要连 pig-mysql“就够了。

1
2
3
4
5
6
7
8
9
10
11
# docker-compose.yml
services:
pig-mysql:
image: mysql:8.0
pig-redis:
image: redis:7
pig-gateway:
image: pig-gateway:latest
environment:
- MYSQL_HOST=pig-mysql # 直接用 service name
- REDIS_HOST=pig-redis

问题来了:本地开发怎么办?

你的代码里写的是 pig-mysql,但你本地的 MySQL 跑在 127.0.0.1。这时候就需要 Hosts 文件出场了——把 pig-mysql 指向 127.0.0.1,代码不用改,直接跑。

所以我的 Hosts 文件里有这么一堆:

1
2
3
4
5
6
# 本地开发环境
127.0.0.1 pig-mysql
127.0.0.1 pig-redis
127.0.0.1 pig-gateway
127.0.0.1 pig-auth
127.0.0.1 pig-upms

切到测试环境排查问题,这些域名要指向测试服务器;和前端联调,可能要指向同事的机器;切到预发环境验证,又是另一套 IP。

这就是为什么我需要一个 Hosts 切换工具。但 SwitchHosts 让我越用越烦。

SwitchHosts 的三宗罪

第一宗:Electron 的原罪

SwitchHosts 基于 Electron 构建。Electron 是什么?简单说,就是把一个完整的 Chrome 浏览器打包进你的应用里。所以一个功能简单的 Hosts 切换工具,安装包 100MB 起步,运行时内存占用几百 MB。

你的电脑里可能同时跑着 VS Code、Slack、Discord、Notion——它们都是 Electron 应用,每个都带着一个 Chrome 内核。你的内存就这样被吃掉了。

第二宗:自动化的缺失

我想在 npm run dev 或者 mvn spring-boot:run 之前,自动切换到开发环境的 Hosts 配置。SwitchHosts 做不到,它只有 GUI,没有命令行。

我想在 CI/CD 流水线里跑集成测试之前自动切换 Hosts。SwitchHosts 也做不到,它需要图形界面。

为什么要自己造轮子

我在 GitHub 上找了一圈,没有满意的替代品。要么是另一个 Electron 应用,要么功能太简陋,要么不支持 CLI。

那就自己写一个。

设计目标我想得很清楚:安装包控制在 5MB 以内,必须支持命令行能在脚本和 CI/CD 里用,还要能直接导入 SwitchHosts 的配置——毕竟大家都配了那么多规则,不能让人从头再来。

技术选型花了点时间。最后选了 Rust + Tauri v2 + Vanilla JS。

为什么是 Rust?编译出来的二进制文件小,运行时不需要额外的运行时环境。为什么是 Tauri?它用系统自带的 WebView 渲染界面,不需要打包一个 Chrome 进去。为什么是 Vanilla JS?我不需要 React 或 Vue 的那些功能,一个 Hosts 切换工具,原生 JS 就够了。

最后的结果:安装包 1MB

没错,1MB。SwitchHosts 的 1/100。我自己都没想到能做到这么小。

Hostly:三个杀手级功能

mBfzvq

功能一:CLI / Headless 模式

这是 Hostly 和 SwitchHosts 最大的区别。

Hostly 提供了完整的命令行支持,不只是 GUI 应用带个命令行参数,而是一个独立的 hostly-core 二进制文件,专门为无 GUI 环境设计。

场景一:开发环境自动切换

在你的启动脚本里加一行:

1
2
# 切换到单选模式,激活 dev 环境
hostly open dev --single

然后正常启动项目。Hosts 已经切好了。

场景二:CI/CD 流水线集成

在 GitHub Actions 或 Jenkins 里:

1
2
# 导入测试配置并立即生效
hostly-core import ./test-env.json --open --multi

跑完测试,再切回去:

1
hostly-core close --names test-env

场景三:服务器 Hosts 管理

通过 SSH 连到一台没有图形界面的服务器,用 hostly-core 管理 Hosts。这在 SwitchHosts 的世界里是不可能的。

Old1yj

功能二:一键迁移 SwitchHosts 配置

我知道你在 SwitchHosts 里配了几十条规则,分了好几个组。舍不得。

Hostly 内置了迁移命令:

1
hostly migration ./SwitchHosts_backup.json

一行命令,所有配置都搬过来,连分组名字都给你保留着。

这是赤裸裸的”抢生意”功能。

技术栈的选择

Tauri vs Electron

这是核心决策。

Electron 的问题在于它打包了一个完整的 Chromium 内核,不管你的应用多简单,这个内核都在那儿,占着 100MB+ 的空间和几百 MB 的内存。

Tauri 不一样。它用系统自带的 WebView:Windows 上是 WebView2(基于 Edge),macOS 上是 WKWebView(基于 Safari),Linux 上是 WebKitGTK。这些 WebView 已经在你的系统里了,不需要额外打包。

结果就是:Tauri 应用的体积可以做到 Electron 的 1/100。

Vanilla JS vs React/Vue

这是一个激进的选择。

现代前端开发,不用框架好像是一种倒退。但我觉得对于 Hostly 这样的简单应用,React 或 Vue 带来的运行时开销是不必要的。原生 JS + 原生 CSS,零运行时开销,界面响应更快,内存占用更低。

硬核参数

维度 SwitchHosts Hostly
安装包体积 100MB+ 1MB
内存占用 几百 MB 极低
CLI 支持 完整
Headless 模式 支持
迁移支持 - 一键迁移
开源协议 Apache 2.0 MIT

立即体验

GitHubhttps://github.com/zengyufei/Hostly/releases/tag/releases

1
2
3
4
5
6
7
8
9
10
11
# 查看帮助
hostly --help

# 列出所有配置
hostly list

# 激活某个环境
hostly open --names Dev --single

# 导出配置
hostly export --target backup.json