终端代理
Recv failure: Connection was reset(git 连 GitHub)
fatal: unable to access 'https://github.com/…': Recv failure: Connection was reset
要点
问:几种报错原文各说明什么?
短答:看末尾那句:reset 是连上后被掐断,Failed to connect 是根本没连上,带 over proxy 的是代理端口不通。
| 报错原文(关键句) | 常见于 | 说明 |
|---|---|---|
| Recv failure: Connection was reset | Windows 上的 git | 连接已经建立,收数据时被对方或路上的设备重置 |
| OpenSSL SSL_read: Connection was reset, errno 10054 | Windows 上用 OpenSSL 后端的 git | 同上,10054 是 Windows 的「连接被重置」错误码 |
| Recv failure: Connection reset by peer | macOS、Linux | 同上,只是措辞不同 |
| Failed to connect to github.com port 443 after 21000 多 ms: Timed out 或 Could not connect to server | 各系统 | TCP 都没建起来,直连时请求被丢弃 |
| Failed to connect to github.com:443 over proxy 127.0.0.1 after … ms | 各系统 | 设了代理,但本机那个端口没有程序在听 |
Connection was reset[报错]连接建立后被一方发来的重置包强行关闭。① 直连 GitHub 时常见,走代理后通常消失;② 走代理仍出现,多半是节点到 GitHub 这一段不稳。参见:git set proxy。
问:先查哪几项?
短答:从「git 有没有设代理」查起,一项项往下排。
-
看 git 读到了哪些代理设置,以及来自哪个文件:
git config --show-origin --get-regexp proxy -
看终端里有没有代理环境变量(git 也读它们):
env | grep -i proxyGet-ChildItem Env: | Where-Object Name -match 'proxy' -
两处都是空的:git 在直连。按 git set proxy 一页给 github.com 单独设代理。
-
设了代理:先确认端口上有程序在听,用下一节的 curl 命令试一次。
-
都没问题却仍被重置:换一个节点重试;几个节点都一样,再查 DNS 有没有被改,方法见 DNS 检测。
问:怎么确认这次请求真的走了代理?
短答:用 curl 带同一个代理地址去连 GitHub,看到 CONNECT 和 200 回应就是通的;再取一次出口 IP,确认从哪出去。
curl -v -x http://127.0.0.1:7890 -o /dev/null https://github.com 2>&1 | grep -E "CONNECT|HTTP/1.1 200"
curl -x http://127.0.0.1:7890 https://chageejichang.co/api/chukou
curl -x http://127.0.0.1:7890 https://ipinfo.io/json
curl.exe -v -x http://127.0.0.1:7890 -o NUL https://github.com 2>&1 | Select-String "CONNECT|HTTP/1.1 200"
curl.exe -x http://127.0.0.1:7890 https://chageejichang.co/api/chukou
连 github.com 的那条正常时,会出现 CONNECT github.com:443 HTTP/1.1 和一行 200 回应(回应后面的文字各客户端略有不同)。chageejichang.co/api/chukou 是本站的出口接口,返回这次请求到达本站时的 IP、国家和 ASN;ipinfo.io 是第三方公开接口,作用相同,本站接口打不开时用它。端口 7890 请改为你客户端里显示的那个。
问:Windows 和 macOS、Linux 的写法差在哪?
短答:git 命令一样,差在环境变量、curl 的名字和空设备的写法。
| 项 | Windows PowerShell | macOS / Linux |
|---|---|---|
| 临时设代理变量 | $env:HTTPS_PROXY = "http://127.0.0.1:7890" |
export HTTPS_PROXY=http://127.0.0.1:7890 |
| curl | curl.exe |
curl |
| 丢弃输出 | -o NUL |
-o /dev/null |
| 筛选输出 | Select-String |
grep |
| 常见的重置报错措辞 | Connection was reset | Connection reset by peer |
问:只有大仓库会被重置,调大 http.postBuffer 有用吗?
短答:多数没用。git 文档说明它管的是向远端 POST 数据时的缓冲区,并写明调大它一般解决不了推送问题,对 clone 被重置更帮不上。
clone 大仓库时连接时间长,中途被掐断的机会更多。可以先浅克隆,只拿末尾那一次提交,连接时间短得多:
git clone --depth 1 https://github.com/git/git
需要完整历史时,再在仓库里执行 git fetch –unshallow 补齐。
问:排查完怎么撤销临时设置?
短答:删掉为测试加的环境变量;git 里的代理设置要不要留,看你以后还用不用代理。
unset HTTPS_PROXY HTTP_PROXY
git config --global --unset http.https://github.com.proxy
Remove-Item Env:HTTPS_PROXY, Env:HTTP_PROXY -ErrorAction SilentlyContinue
git config --global --unset http.https://github.com.proxy
问:什么时候才算线路问题?
短答:git 确认走了代理、换过几个节点,仍然稳定复现重置,才轮到线路。
这时浏览器访问 GitHub 往往也会出现 err_connection_reset,两边同时出问题,说明是节点到 GitHub 这一段不通,而不是 git 的设置。可以先看出口落在哪、被判成什么类型,再决定是换节点还是看本页下方的简表。换节点时一次只改一处,改完立刻用上面的 curl 命令复测,记下每个节点的结果,才分得清是哪一段出了问题。