在终端中快速设置代理

本文最后更新于 2025年5月15日 晚上

平常使用代理去访问 Github,Google 之类的网站时,只需要在代理软件中启用系统代理就行,这很简单的嘛。

但在终端中,使用 Git 命令去下载 Github 项目或者访问其他需要代理的网站时,啊咧,怎么访问失败了,明明在代理软件中开了系统代理,怎么会访问不了呢,怎么会是呢?

其实代理软件设置系统代理后,只有主动使用系统代理的软件,比如浏览器等,才能吃到代理,正常访问 Github 之类的网站。但一些有自己代理设置的软件,比如终端,并不会主动使用代理,所以就出现开启系统代理后仍然访问不了的问题。

如果代理软件有虚拟网卡模式,或者 TUN 模式,打开后就能简单解决这个问题。

虚拟网卡模式和 TUN 模式可以模拟一张网卡,使所有流量都经过代理软件,这样即使软件不使用系统代理,软件也会走代理。

在代理软件中,还有个全局模式,但实际上并不能让不使用系统代理的软件走代理。嗯?难道全局模式是假的吗?

其实不假,只是全局模式作用和通常想的不一样。

全局模式是指走代理软件的流量全部走代理服务器,如果改成绕过国内则是走代理软件的流量中,一部分仍然直连,一部分走代理服务器。而虚拟网卡模式和 TUN 模式是调整代理软件在系统中的作用范围,禁用时,只有部分的软件走代理软件,启用时,所有的软件都要走代理软件。

听到这,应该知道虚拟网卡模式和 TUN 模式为什么能解决上面的问题了吧。嗯…还是听不懂嘛,没关系,能访问 Google 的话可以自己查找关于代理软件的 TUN 模式的文档哦,还可以去问问 ChatGPT。这东西讲起来内容有些多,就不在这细讲了。

似乎,开了 TUN 模式后,所有软件都会走代理软件了(不知道是错觉还是真的,网络延迟还变高了呢,可能是流量要多经过一次代理软件的虚拟网卡,增加了处理时间了)。但自己只想让终端使用代理,不如换个方式,调整终端的代理设置吧。

终端里通常使用 HTTP_PROXY 和 HTTPS_PROXY 环境变量来配置代理,将变量的值设置为代理服务器的值就行,再设置 NO_PROXY 环境变量来避免奇奇怪怪的问题。比如从代理软件中知道代理服务器地址是 http://127.0.0.1:10808 ,则在不同终端中设置代理的命令如下。

  • PowerShell
1
2
3
$Env:HTTP_PROXY = "http://127.0.0.1:10808"
$Env:HTTPS_PROXY = "http://127.0.0.1:10808"
$Env:NO_PROXY = "localhost,127.0.0.1,::1"
  • MSYS2 / Git Bash / Linux Shell / Unix Shell
1
2
3
export HTTP_PROXY="http://127.0.0.1:10808"
export HTTPS_PROXY="http://127.0.0.1:10808"
export NO_PROXY="localhost,127.0.0.1,::1"
  • CMD
1
2
3
set HTTP_PROXY=http://127.0.0.1:10808
set HTTPS_PROXY=http://127.0.0.1:10808
set NO_PROXY=localhost,127.0.0.1,::1

但是命令设置的环境变量只是临时环境变量,呜,好麻烦啊。唔…终端好像能编写函数,像命令一样调用…诶?!编写一个函数来做这种事不就好了嘛。这里就用 Visual Studio Code 来编写函数吧。

  • PowerShell

PowerShell 是 Windows 系统里比较常用的终端,下面就先打开 PowerShell,把下面的命令复制进 PowerShell 后回车运行一下。

1
2
New-Item -ItemType Directory -Path "$([System.Environment]::GetFolderPath("MyDocuments"))\WindowsPowerShell"
New-Item -ItemType File -Path "$([System.Environment]::GetFolderPath("MyDocuments"))\WindowsPowerShell\Microsoft.PowerShell_profile.ps1"

运行后将在 C:\User\YourUserName\Documents\WindowsPowerShell 这个路径创建一个 Microsoft.PowerShell_profile.ps1 文件,这是 PowerShell 的配置文件,可以在里面编写函数。

呀,差点忘了要解锁 PowerShell 运行脚本的限制了,再运行一下下面的命令吧。

1
Set-ExecutionPolicy Unrestricted -Scope CurrentUser

接下来找到那个目录,用 Visual Studio Code 打开吧,把下面的代码复制进去吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
function global:Set-Proxy { # 设置代理
param (
$proxy_value
)

if ([string]::IsNullOrEmpty($proxy_value)) {
$internet_setting = Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
if ($internet_setting.ProxyEnable -ne 1) {
Write-Host "未启用系统代理"
return
}

# 提取代理地址
$proxy_addr = $($internet_setting.ProxyServer)
if (($proxy_addr -match "http=(.*?);") -or ($proxy_addr -match "https=(.*?);")) {
$proxy_value = $matches[1]
# 去除 http / https 前缀
$proxy_value = $proxy_value.ToString().Replace("http://", "").Replace("https://", "")
$proxy_value = "http://${proxy_value}"
} elseif ($proxy_addr -match "socks=(.*)") {
$proxy_value = $matches[1]
# 去除 socks 前缀
$proxy_value = $proxy_value.ToString().Replace("http://", "").Replace("https://", "")
$proxy_value = "socks://${proxy_value}"
} else {
$proxy_value = "http://${proxy_addr}"
}
}

$Env:NO_PROXY = "localhost,127.0.0.1,::1"
$Env:HTTP_PROXY = $proxy_value
$Env:HTTPS_PROXY = $proxy_value
Write-Host "设置代理完成, 代理地址: $Env:HTTP_PROXY"
}

function global:Unset-Proxy { # 清除代理
if ([string]::IsNullOrEmpty($Env:HTTP_PROXY)) {
Remove-Item -Path Env:HTTP_PROXY -Force
}
if ([string]::IsNullOrEmpty($Env:HTTPS_PROXY)) {
Remove-Item -Path Env:HTTPS_PROXY -Force
}
Write-Host "清除代理完成"
}

复制进去后保存一下就行了。等等,PowerShell 的配置文件需要特殊的文件编码来保存哦。在 Visual Studio Code 里按下 Ctrl + Shift + P,顶上就打开 Visual Studio Code 的功能查找,在上面输入 Change File Encoding,可以看到更改文件编码这个选项,选择一下,再选一下通过编码保存,在编码列表里选择 UTF-8 with BOM,大功告成。

现在再重新打开 PowerShell 就可以用上刚刚编写的函数,输入 Set-Proxy 后,终端就配置好代理了,再试试之前的命令去访问 Github 什么的,网络问题都消失了,好神奇,好方便。

嗯… Set-Proxy 这个命令是自动读取系统代理来设置代理的,如果我知道代理地址,比如 http://127.0.0.1:10808 ,想设置成这个呢?这也是可以的哦。只要 Set-Proxy http://127.0.0.1:10808 就行了呢。

不想使用代理了,想清除刚刚设置的代理,该怎么办呢?很简单,把 PowerShell 重新打开就好了嘛,但是…这样有些麻烦。没关系,刚刚编写的函数里就有一个快速清除代理的函数,运行一下 Unset-Proxy 就好了。

  • MSYS2 / Git Bash / Linux Shell / Unix Shell

有时使用的终端不是 PowerShell,而是这几个,也可以像 PowerShell 一样编写函数呢。打开终端后,用命令新建一个 sh 文件来编写函数。

1
touch "${HOME}/custom_cmd.sh"

运行后会在 /home/YourUserName 这个路径新建一个 custom_cmd.sh 文件(这里要注意一下,MSYS2 / Git Bash 的 home 目录是在安装这个终端的路径中的哦),用 Visual Studio Code 打开这个文件吧,把下面的函数粘贴进去。

在 MSYS2 / Git Bash 中可以通过 cygpath 命令查看 home 目录对应的 Windows 真实路径,用法是cygpath -w "<要查看的路径>",比如查看 home 目录的真实路径:

1
cygpath -w "${HOME}"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
get_windows_system_proxy_config_code() { # 获取 Windows 系统代理地址的 PowerShell 代码
cat<<EOF
# 读取注册表配置
\$internet_setting = Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"
\$proxy_addr = \$(\$internet_setting.ProxyServer)

# 提取代理地址
if ((\$proxy_addr -match "http=(.*?);") -or (\$proxy_addr -match "https=(.*?);")) {
\$proxy_value = \$matches[1]
# 去除 http / https 前缀
\$proxy_value = \$proxy_value.ToString().Replace("http://", "").Replace("https://", "")
\$proxy_value = "http://\${proxy_value}"
} elseif (\$proxy_addr -match "socks=(.*)") {
\$proxy_value = \$matches[1]
# 去除 socks 前缀
\$proxy_value = \$proxy_value.ToString().Replace("http://", "").Replace("https://", "")
\$proxy_value = "socks://\${proxy_value}"
} else {
\$proxy_value = "http://\${proxy_addr}"
}

if (\$internet_setting.ProxyEnable -eq 1) {
Write-Host \$proxy_value
}
EOF
}

get_system_proxy_address() { # 获取系统代理地址
local gsettings_proxy_status
local gsettings_http_host
local gsettings_http_port
local gsettings_http_proxy_config
local gsettings_socks_host
local gsettings_socks_port
local gsettings_socks_proxy_config
local kde_proxy_status
local kde_http_proxy_config
local kde_socks_proxy_config
local windows_proxy_config
local macos_proxy_config

if [[ "${OSTYPE}" == "msys"* ]] || [[ "${OSTYPE}" == "cygwin"* ]]; then
windows_proxy_config=$(powershell -c "$(get_windows_system_proxy_config_code)" 2> /dev/null)
echo "${windows_proxy_config}"
elif [[ "${OSTYPE}" == "linux"* ]]; then
# 获取代理设置状态
gsettings_proxy_status=$(gsettings get org.gnome.system.proxy mode 2> /dev/null | sed "s/'//g") # Gnome
kde_proxy_status=$(cat ~/.config/kioslaverc 2> /dev/null | grep "ProxyType" | awk -F 'ProxyType=' '{print $NF}') # KDE

# 判断代理设置
if [[ "${gsettings_proxy_status}" == "manual" ]]; then
gsettings_http_host=$(gsettings get org.gnome.system.proxy.http host 2> /dev/null | sed "s/'//g")
gsettings_http_port=$(gsettings get org.gnome.system.proxy.http port 2> /dev/null)
gsettings_socks_host=$(gsettings get org.gnome.system.proxy.socks host 2> /dev/null | sed "s/'//g")
gsettings_socks_port=$(gsettings get org.gnome.system.proxy.socks port 2> /dev/null)
gsettings_http_proxy_config="http://${gsettings_http_host}:${gsettings_http_port}"
gsettings_socks_proxy_config="socks://${gsettings_socks_host}:${gsettings_socks_port}"

if [[ ! -z "${gsettings_http_host}" ]] && [[ ! -z "${gsettings_http_port}" ]]; then
echo "${gsettings_http_proxy_config}"
elif [[ ! -z "${gsettings_socks_host}" ]] && [[ ! -z "${gsettings_socks_port}" ]]; then
echo "${gsettings_socks_proxy_config}"
fi
elif [[ "${kde_proxy_status}" == 1 ]]; then
kde_http_proxy_config=$(cat ~/.config/kioslaverc 2> /dev/null |\
grep "httpProxy=" |\
awk -F 'httpProxy=' '{gsub(/ /, ":"); print $NF}' \
)
kde_socks_proxy_config=$(cat ~/.config/kioslaverc 2> /dev/null |\
grep "socksProxy=" |\
awk -F 'socksProxy=' '{gsub(/ /, ":"); print $NF}' \
)

if [[ ! -z "${kde_http_proxy_config}" ]]; then
echo "${kde_http_proxy_config}"
elif [[ ! -z "${kde_socks_proxy_config}" ]]; then
echo "${kde_socks_proxy_config}"
fi
fi
elif [[ "${OSTYPE}" == "darwin"* ]]; then
macos_proxy_config=$(scutil --proxy 2> /dev/null | awk ' \
/HTTPEnable/ { http_enabled = $3; } \
/HTTPProxy/ { http_server = $3; } \
/HTTPPort/ { http_port = $3; } \
/SOCKSEnable/ { socks_enabled = $3; } \
/SOCKSProxy/ { socks_server = $3; } \
/SOCKSPort/ { socks_port = $3; } \
END { \
if (http_enabled == "1") { \
print "http://" http_server ":" http_port; \
} else if (socks_enabled == "1") { \
print "socks://" socks_server ":" socks_port; \
} \
}' \
)
echo "${macos_proxy_config}"
fi
}


set_proxy() { # 设置代理功能
local proxy_value

if [[ -z "$*" ]]; then
proxy_value=$(get_system_proxy_address)
if [[ -z "${proxy_value}" ]]; then
echo "未启用系统代理"
return 1
fi
else
proxy_value=$@
fi

export NO_PROXY="localhost,127.0.0.1,::1"
export HTTP_PROXY=$proxy_value
export HTTPS_PROXY=$proxy_value
echo "设置代理完成, 代理地址: ${proxy_value}"
}


unset_proxy() { # 取消代理功能
unset HTTP_PROXY
unset HTTPS_PROXY
echo "清除代理完成"
}

粘贴后保存一下就行,这里就不需要特意去修改文件保存编码了。Visual Studio Code 默认使用的 UTF-8 来保存文件编码,使用这个编码就行了,这和 PowerShell 有些区别哦。

此时需要知道此时的终端用的是 Bash,Zsh 或者是其他的终端解释器,就用下面的命令去查看吧。

1
echo "${SHELL#/usr/bin/}"

如果显示的是 bash,则配置文件是 .bashrc;如果显示的是 zsh,则配置文件是 .zshrc,显示的是其他的话就自己在 Google 上查找吧,应该都能查到的。一般配置文件都在 /home/YourUserName 这个路径里,没找到对应的配置文件就自己创建一个吧。

然后打开这个配置文件,在配置文件里写下初始化刚刚编写函数的文件的命令。

1
. "${HOME}/custom_cmd.sh"

保存一下,再重启一下终端,此时就可以像 PowerShell 一样中设置代理了,用法和在 PowerShell 中的一样,只不过… Set-Proxy 要替换成 set_proxy,Unset-Proxy 要替换成 unset_proxy,其他的就和 PowerShell 中的一样了。

嗯…总感觉少了点什么…

啊咧,怎么没有在 CMD 中的教程呢?啊哈哈,CMD 我不怎么用,就不教怎么弄了(其实我也不会弄,诶嘿),把在 PowerShell 中的方法扔给 ChatGPT 或者 DeepSeek 这些 AI,让 AI 改成 CMD 上能用的就行了。

听说有些软件只吃 ALL_PROXY 这个环境变量,嗯…我到现在还没遇到那种软件呢,不过遇上的话就把上面的函数改改就行了,应该很简单的吧,而且还有 AI 可以帮你改呢。


这首歌好听,就顺手推荐一下了。

砂糖和盐最好了~


在终端中快速设置代理
https://licyk.netlify.app/2025/02/02/set-proxy-in-terminal/
作者
licyk
发布于
2025年2月2日
许可协议