终端代理环境变量怎么设:HTTP_PROXY、HTTPS_PROXY 与 NO_PROXY 的写法、生效范围与常见坑
很多开发者都遇到过这种割裂:系统已经连上了线路,浏览器打开境外网站一切正常,可一切换到终端,git clone 卡在「Cloning into」,pip install 报连接超时,curl 请求半天没有响应。原因是大多数命令行工具不读系统代理设置,它们只认几个约定俗成的环境变量:HTTP_PROXY、HTTPS_PROXY、ALL_PROXY 和 NO_PROXY。没设这几个变量,终端里的请求就会绕开系统代理直接出去。
问题在于,这几个变量并没有统一标准。有的工具只认小写,有的工具大小写都认但优先级不同;NO_PROXY 的写法在不同工具里支持程度也不一样,有的认网段,有的只认域名后缀;还有一批工具压根不读环境变量,要单独配置。于是常见的抱怨就成了「设了不生效」「设了之后内网挂了」「加了 sudo 代理没了」。下面先把各个变量的含义和各工具的读取差异讲清,再给出各系统的设置步骤与排错对照。
几个代理变量的含义与读取差异
最省心的做法是大小写各设一份,保证所有工具都能读到。HTTPS_PROXY 的值通常写 http 开头而不是 https 开头,因为这里描述的是「怎么连到代理」,本地代理端口本身一般是明文协议;写成 https 开头反而会在部分工具里报握手错误。端口以客户端设置页显示为准。
| 变量 | 作用 | 大小写情况 | 常见取值 |
|---|---|---|---|
| HTTP_PROXY | 明文网址请求走的代理 | curl 只认小写形式 | http://127.0.0.1:端口 |
| HTTPS_PROXY | 加密网址请求走的代理 | 多数工具大小写都认 | http://127.0.0.1:端口 |
| ALL_PROXY | 未单独指定协议时的兜底代理 | curl 等支持,部分工具不认 | socks5h://127.0.0.1:端口 |
| NO_PROXY | 不走代理的地址列表 | 多数工具大小写都认 | localhost,127.0.0.1,内网域名 |
| 工具自带配置 | git、npm 等自己的代理设置 | 与环境变量并存 | 写在各自配置文件里 |
| 系统代理设置 | 浏览器与部分图形程序读取 | 命令行工具多数不读 | 在系统设置中配置 |
各系统的设置步骤
- 第一步:先把网络线路准备好。连上刺猬VPN,确认浏览器能打开境外网站;客户端开全局模式时终端流量多数情况下直接生效,可以先跳到第六步验证,不生效再回来设置变量;
- 第二步:在客户端设置页找到本地代理端口,记下 HTTP 端口号,后面的变量都指向 127.0.0.1 加这个端口;
- 第三步:macOS 与 Linux 在当前终端执行 export https_proxy 与 http_proxy 两条命令,再执行同名的大写版本;想长期生效,就把这几行写进用户目录下的 .zshrc 或 .bashrc,保存后重新打开终端;
- 第四步:Windows 的 PowerShell 用 $env:HTTPS_PROXY 赋值,只对当前窗口有效;长期生效用 [Environment]::SetEnvironmentVariable 写到用户级变量,或者在系统设置的「环境变量」窗口里手动添加,写完要重新打开终端;
- 第五步:Windows 的 CMD 用 set 设置当前窗口,用 setx 写入用户变量,注意 setx 不影响已经打开的窗口;
- 第六步:验证。执行 curl -I https://www.google.com,能返回状态行说明加密请求已经走通;再执行 env 或 Get-ChildItem Env: 查看变量是否真的存在,拼写错误是最常见的失败原因;
- 第七步:设置 NO_PROXY。至少写上 localhost、127.0.0.1 和公司内网域名后缀,多个值用英文逗号分隔,不要加空格;
- 第八步:给不读环境变量的工具单独配置。git 用 git config --global http.proxy,npm 用 npm config set proxy 与 https-proxy,Docker 守护进程要在服务配置里单独写代理,详见下文。
按现象排查:为什么设了不生效
环境变量出问题,九成是「谁在读、读的是哪一个」没对上,按现象逐条对照。
- curl 访问明文网址不走代理:curl 出于安全原因忽略大写的 HTTP_PROXY,只读小写的 http_proxy,补一份小写变量;
- git clone 的 https 地址正常、git@ 开头的地址仍然超时:后者走的是 SSH 协议,不读这些变量,要在 SSH 配置里为目标主机写 ProxyCommand,或者把远端地址改成 https 形式;
- 加了 sudo 之后代理失效:sudo 默认清空大部分环境变量,用 sudo -E 保留,或者在 sudoers 里把这几个变量加进保留列表;
- Node.js 脚本里的请求不走代理:Node 内置的请求模块默认不读这些变量,要在代码里引入代理库并显式配置,或者使用新版本提供的开关,以官方文档为准;
- 设置代理后公司内网接口打不开:NO_PROXY 没写内网域名,请求被送进了代理,补上内网域名后缀与网段;
- NO_PROXY 写了网段仍然被代理:部分工具不支持网段写法,只认域名或单个地址,改写成具体地址;
- 报 Proxy CONNECT aborted 或 Received HTTP code 400 from proxy:端口填错,或者把 SOCKS 端口当成 HTTP 端口用了,核对客户端里的端口类型。
几种让终端走线路的方式对比
三种方式并不冲突。全局模式最省事,适合临时装一堆依赖;环境变量更精细,适合长期开发、需要和内网共存的场景;git、npm 这类高频工具再单独配一次,避免哪天忘记设置变量。实际可用性取决于当前网络环境。
| 对比项 | 客户端全局模式 | 环境变量 | 工具自带配置 |
|---|---|---|---|
| 覆盖范围 | 整机流量 | 读取变量的程序 | 只对该工具 |
| 设置成本 | 一键切换 | 每个终端或写进配置文件 | 每个工具单独设置 |
| SSH 与 UDP | 可以覆盖 | 不覆盖 | 视工具而定 |
| 内网兼容 | 依赖智能分流规则 | 靠 NO_PROXY 控制 | 靠工具自己的排除规则 |
| 适合场景 | 临时全量使用 | 日常开发 | 长期固定使用的工具 |
| 线路选择 | 免费节点永久免费、不限流量、不限速 | 会员节点有效期内不限流量、不限速 | 同左 |
Docker、IDE 与 CI 里的变量传递
Docker 是最容易踩坑的地方,因为它有三层:拉取镜像的是守护进程,它不读你终端里的变量,要在守护进程的服务配置里单独设置代理并重启服务;构建镜像时容器内的命令要通过构建参数传入代理变量;运行中的容器则要在启动参数里传入。三层各管各的,只设一层就会出现「镜像拉得动、构建时装不了依赖」之类的半通状态。
IDE 内置终端一般继承启动 IDE 时的环境,如果你是先打开 IDE、后改的变量,内置终端读不到新值,要完全退出 IDE 再打开。CI 流水线的变量则应写在流水线配置或密钥管理里,构建机多数位于境外时根本不需要代理,盲目设置反而会因为找不到本地端口而失败。
还有一个容易混淆的点:容器内的 127.0.0.1 指的是容器自己,而不是宿主机。在容器里把代理变量写成 127.0.0.1 加端口,请求会发到容器内部一个并不存在的服务上,表现为连接被拒绝。正确做法是写宿主机在容器网络里的地址,桌面版 Docker 通常可以用一个专门指向宿主机的主机名,同时本地代理端口要能接受来自容器网络的连接,是否支持以及对应选项以客户端设置页为准。
常用工具的读取规则对照
这份对照的意义在于:遇到某个工具不走代理时,先确认它属于哪一类,是读变量、读自己的配置,还是两者都不读。属于后两类的,再怎么改环境变量也没用,直接去改它自己的配置文件才是正解。各工具版本更新后行为可能变化,以官方文档为准。
- curl:小写与大写的 HTTPS_PROXY 都认,明文请求只认小写的 http_proxy;支持 ALL_PROXY 和 socks5h 写法;较新的版本支持在 NO_PROXY 里写网段;
- git:通过 https 协议克隆时读取环境变量,也会读取自己的 http.proxy 配置,两者同时存在时以 git 配置为准;SSH 协议的远端完全不受影响;
- Python 的 pip 与常见请求库:大小写变量都认,pip 还支持命令行的 proxy 参数,临时指定时最直接;
- Go 工具链:大小写都认,大写优先,NO_PROXY 支持网段;下载模块时更推荐配置模块代理,而不是走网络代理;
- npm 与 yarn:优先读取各自配置文件里的代理项,配置文件里残留的旧地址会覆盖环境变量,排查时先看配置;
- Java 与 Maven、Gradle:多数情况下不读这些环境变量,要在 settings.xml 或 gradle.properties 里写代理主机和端口;
- wget:读取小写变量,也可以在用户目录的配置文件里写死,使用方法与 curl 接近。
与相关话题的分工
环境变量里填的到底应该是 HTTP 端口还是 SOCKS 端口,取决于工具支持哪种协议,两种代理协议的差别与适用场景见 SOCKS5 与 HTTP 代理的区别。如果你的目的是加快 npm、pip、Maven 这些包仓库的下载,换国内镜像源往往比走代理更直接,各仓库的镜像配置方法见 开发包仓库访问与镜像配置。
两者的边界是:国内镜像覆盖得到的仓库优先用镜像,镜像没有同步的、或者必须访问官方源的场景再用代理变量。镜像与代理同时配置时,要用 NO_PROXY 把镜像域名排除掉,避免请求绕一圈出境再回来。
常见报错速查表
| 现象 | 原因 | 解决办法 |
|---|---|---|
| curl 明文请求不走代理 | 只认小写 http_proxy | 补设小写变量 |
| git@ 地址超时 | SSH 不读代理变量 | 配置 ProxyCommand 或改用 https 地址 |
| sudo 后代理消失 | sudo 清空环境变量 | 使用 sudo -E 或设置保留列表 |
| 内网接口打不开 | NO_PROXY 未包含内网 | 补上内网域名后缀 |
| Received HTTP code 400 from proxy | 端口类型填错 | 核对 HTTP 与 SOCKS 端口 |
| docker pull 超时 | 守护进程未配置代理 | 在服务配置中设置并重启 |
| 新开终端变量消失 | 只在当前窗口设置 | 写进 shell 配置或用户环境变量 |
高频问答
- 问:HTTPS_PROXY 的值应该写 https 开头吗?答:通常写 http 开头,它描述的是连接本地代理的方式,本地代理端口多为明文协议;
- 问:socks5 和 socks5h 有什么区别?答:带 h 的写法让代理端解析域名,能避免本地域名解析被干扰,curl 支持这种写法;
- 问:设了变量会影响浏览器吗?答:一般不会,浏览器读取的是系统代理设置;
- 问:NO_PROXY 要不要写星号?答:多数工具用前置点号表示子域名,比如写点号加公司域名,星号的支持程度不一致;
- 问:为什么 pip 能用 npm 不能用?答:npm 有自己的代理配置项,优先于环境变量,检查 npm config 里是否残留了旧的代理地址;
- 问:用完要不要删掉变量?答:断开线路后本地端口不再监听,残留变量会让所有请求失败,用完执行 unset 或关闭窗口。
把终端代理一次配好
终端代理环境变量看起来简单,真正稳定下来要做到三点:HTTP_PROXY、HTTPS_PROXY 大小写各设一份,NO_PROXY 写全本地与内网地址,git、npm、Docker 这些不读变量的工具单独配置。把这些写进 shell 配置文件或 dotfiles 仓库,换电脑时一次恢复,就不会再遇到「浏览器能开、终端超时」的割裂。
刺猬VPN 支持自定义用户名和密码匿名注册,不需要邮箱、也不需要手机号,采用 HTTPS+AES 加密传输;免费节点永久免费、不限流量、不限速,适合先验证终端变量是否配置正确;时长套餐有效期内不限流量、不限速,适合每天拉依赖、克隆仓库的开发者,一个账号支持多设备同时在线。客户端带断线保护和按域名、IP 的智能分流,内网与国内服务照常直连。实际可用性取决于当前网络环境。
立即下载刺猬VPN:从注册到连接,三分钟完成
刺猬VPN提供永久免费节点,不限流量;无需邮箱,自定义用户名即可匿名注册。一个账号支持多设备同时在线,实际可用性取决于当前网络环境。