现象:浏览器正常,终端工具却直连失败
很多开发者在系统里配好了代理,浏览器访问正常,但打开终端跑 curl、git clone、npm install 却依旧直连失败。根本原因是系统代理设置和命令行工具读取的代理配置是两套机制,互不相通。
原因一:大小写与作用域问题
不同工具读取代理变量的规则差异
HTTP_PROXY 和 http_proxy 在部分工具里是两个不同的变量,curl 两者都识,但部分语言运行时只识小写。另外,用 export 声明的变量只对当前 shell 会话及其子进程生效,新开的终端窗口或 CI 运行环境默认不会继承。git 更特殊,它优先读 ~/.gitconfig 里的 http.proxy 配置项,即使环境变量设对也会被配置文件里的旧值覆盖。
原因二:系统代理不等于进程级代理
系统网络设置里的代理开关主要面向图形化应用(浏览器、邮件客户端等),大多数命令行工具并不会主动读取这个系统设置,必须通过环境变量或工具自身配置文件单独告知。这也是为什么浏览器能连但终端不行的根本原因。
原因三:NO_PROXY 配置不当
NO_PROXY 用于声明哪些地址不走代理,常见错误有两种:一是把内网地址段写得过宽,误将需要走代理的域名也排除在外;二是完全未配置,导致访问内网服务(比如公司内部 GitLab)也被绕道进代理,反而报错。
逐项验证方法
| 排查项 | 验证命令 | 预期结果 |
|---|---|---|
| 环境变量是否生效 | env | grep -i proxy | 大小写变量都能看到预期值 |
| git 是否走了自己的配置 | git config --global --get http.proxy | 为空或与环境变量一致 |
| NO_PROXY 是否误排除目标域名 | echo $NO_PROXY | 不包含需要走代理的域名 |
| 实际请求是否真走代理 | curl -v https://example.com | 日志里能看到 CONNECT 代理握手记录 |
各工具读哪里:一张速查表
| 工具 | 优先读取 | 回退来源 |
|---|---|---|
| curl | -x 命令行参数 | http_proxy、HTTPS_PROXY、ALL_PROXY |
| git | http.proxy 配置项 | 底层 curl 读取的环境变量 |
| npm | proxy、https-proxy 配置项 | HTTPS_PROXY、HTTP_PROXY 环境变量 |
| pip | --proxy 参数或 PIP_PROXY | 标准代理环境变量 |
各工具对变量名大小写的处理并不统一,最稳妥的做法是 http_proxy 与 HTTP_PROXY 两种写法同时设置,值保持一致。
NO_PROXY 的写法为什么在不同工具里表现不一
NO_PROXY 是逗号分隔的列表,但匹配规则没有统一标准:有的工具支持以点开头的后缀匹配,有的不支持 *.example.com 这种通配写法;CIDR 网段写法也不是处处可用,curl 的官方文档注明 CIDR 是 7.86.0 版本才加入的。因此建议写具体域名加后缀,并在实际用到的每个工具里各验证一次,不要默认“一处写对,处处生效”。
五步最小排查流程
- 执行
env | grep -i proxy,确认变量是否真的存在,以及大小写两组是否一致; - 用
curl -v -x 代理地址 目标地址显式指定代理,如果显式指定能通、不指定不通,问题就在变量没有传到; - 用
curl -v --noproxy '*' 目标地址做直连对照,确认故障出在链路还是代理配置; - 对 git、npm 等工具,分别用它们自己的 config 命令查看有没有覆盖环境变量的旧值;
- 回到真正出问题的运行环境(sudo、容器、CI、IDE 内置终端)重复第一步,因为这些环境往往不继承当前终端的变量。
NasaCode 的解决思路
与其逐个工具配环境变量,不如直接用 NasaCode 客户端的智能路由在系统层接管流量,不依赖单个工具是否主动识别代理变量,从根本上避免“浏览器行但 CLI 不行”这类参差。
常见问题
为什么 sudo 命令下代理又失效了?
sudo 默认会清空当前用户的环境变量,需要用 sudo -E 保留环境,或在 /etc/sudoers 里显式白名单代理相关变量。
Docker 容器内为什么看不到宿主机的代理设置?
容器是独立网络命名空间,宿主机的环境变量默认不会传递进去,需要在 docker run 时用 -e 显式传入或在 Dockerfile 里单独声明。









