导出 API 端点的 VPN 钩子改变的是它启动的那些进程的环境,而不是隧道建立时已经打开的那个终端。正是这一处区别,解释了大多数「工具仍在调用公共端点」的报告。设置有两个可行的放置位置,选哪个取决于谁来使用它、它多久变一次。在再加一个启动脚本之前,先把两者比较清楚。

设置可以放置的两个位置

第一种是在命令本身前面加前缀:值只属于那一次调用,随调用结束而消失。第二种是在连接钩子里导出,它会覆盖钩子此后启动的每一个进程。两者的差别在作用范围和生命周期上,而不在写法上,这个差别决定了大多数故障。

PropertyPrefix on the commandExport from the hook
Who receives itThat invocation onlyChildren the hook starts
LifetimeUntil the process exitsUntil the hook's own session ends
LeakageScoped to one commandApplies to later commands in that session
Repeat costEvery invocationOnce per connection
Works for an open editorNo, unless the editor is started with itNo

表格让钩子看起来便宜,却藏起了真正的账单:它也会给与任务无关的命令选中私有端点。请把每一行当成约束而不是偏好。如果端点按任务变化,前缀在精确性上胜出,哪怕要多敲一次键。

为什么钩子够不到已经打开的终端

环境变量在进程映像创建时交给进程。在连接之前启动的终端保留着它拿到的那一份副本,而在钩子里执行的导出并不是向机器上每个进程广播。只有钩子自己的子进程会继承它。终端自己的子进程取的是它们启动那一刻终端持有的内容,所以同一条命令可以在一个终端里成功,在另一个里失败。

图形编辑器同样如此。它的扩展宿主、内置终端和后台语言服务器在启动时就已经分叉,各自持有副本。重新打开文件夹并不一定会重启这些子进程,所以你加上的设置依然到不了它们。

最省事的验证,是从失败的地方打印这个变量,而不是从能用的终端里打印。如果失败的进程是在隧道之前启动的,这次导出从一开始就没有机会。

按命令使用的写法

把设置写成前缀,选择就留在使用它的命令里,端点在不同任务间变化时这一点很有用:

env INTERNAL_API='https://internal-api.example.net:8443' my-work-tool

这条命令只是示例:my-work-tool 是占位符,INTERNAL_API 也不是 VPN 的标准,请换成你真正运行的程序的文档化设置,以及你自己批准的主机。不要把令牌或密码写在同一行,它们会留在终端历史里。

当多条命令属于同一项任务时,用一个经过审阅的短包装脚本先设置变量,再启动它们。这样只保留一处定义,又不会把这个值变成终端里后续每条命令的全局设置。

重新加载、重启,还是放着不动

对已经在运行的工具,优先用它自己的重新加载或工作区配置。否则先保存工作,再重启真正读取该设置的那个组件——它往往是语言服务器,而不是编辑器窗口。只重启窗口、假定子进程也跟着重启,正是重新加载看起来不生效的原因。

断开连接是另一件事。暂停、关闭或重连属于应用自己的逻辑,端点变量并不控制它。把这个变量当作选择地址的配置,而不是规定之后允许使用哪些网络流量的规则,两件事就可以分开处理。

相关文章