在MacOS或Linux系统中,使用命令行进行一些操作或执行一些脚本时,我们经常会遇到以下问题:
- 部分链接需要使用代理才能访问;
- 如果设置了代理,则很多不需要代理的链接访问速度会变得很慢;
- 代理是按照流量收费的,不希望那些不需要代理的链接走代理通道。
- 工作环境很复杂、有一些链接只能通过代理访问
在系统代理中,通常可以通过设置PAC(Proxy auto-config)
脚本实现系统自动判断网络链接是否需要走代理,但在命令行中由于curl没有JavaScript功能,因此无法支持PAC实现自动代理。
为了解决这个问题,我们可以编写自定义脚本替代curl命令,使curl支持PAC功能。在进行命令替换操作之前,请先安装quickjs
。
# homebrebrew
brew install quickjs
# Ubuntu 原生使用
# apt install quickjs
# 其他系统按各自方法安装
具体替换用的curl实现代码如下:
#!/bin/bash
# 优先使用 PAC_PATH
PAC_PATH=~/.hosts/pac.loc/pac.js
PAC_URL=http://127.0.0.1/pac.js
CURL_BINARY_PATH=/usr/local/opt/curl/bin/curl
# CURL_BINARY_PATH=/usr/bin/curl
QJS_BINARY_PATH=/usr/local/bin/qjs
# main
REQUEST_URI=""
SKIP_NEXT=false
ARGS=""
for arg in "$@"; do
if [[ "$arg" == -* ]]; then
ARGS="${ARGS} ${arg}"
else
ARGS="${ARGS} '$(sed -r "s:([']):\\\1:g" <<< "${arg}")'"
fi
if [[ ${SKIP_NEXT} == true ]]; then
SKIP_NEXT=false
else
if [[ ${arg} =~ ^https?:// ]]; then
REQUEST_URI="${arg}"
fi
fi
if [[ ${arg} == "--proxy" || ${arg} == "-x" ]]; then
SKIP_NEXT=true
fi
done
if [[ "${REQUEST_URI}" == "" ]]; then
sh -c "${CURL_BINARY_PATH} ${ARGS}"
else
SCRIPT="
$([[ "${PAC_PATH}" == "" ]] && ${CURL_BINARY_PATH} -s "${PAC_URL}" || cat "${PAC_PATH}")
const args = '${REQUEST_URI}'.match(/^[a-zA-Z]+:\/\/([^/]+)/);
const proxy = FindProxyForURL(...args);
if(proxy !== 'DIRECT') {
const [proto,host] = proxy.split(/[ ;]+/);
if(proto === 'SOCKS5') {
console.log('--proxy socks5h://' + host);
}
if(proto === 'PROXY') {
console.log('--proxy ' + host);
}
}
"
PROXY="$(${QJS_BINARY_PATH} -e "${SCRIPT}")"
sh -c "${CURL_BINARY_PATH} ${PROXY} ${ARGS}"
fi
将以上代码保存为~/.curl_with_pac.sh
并添加执行权限chmod +x ~/.curl_with_pac.sh
。然后编辑~/.zshrc
文件新增如下配置:
alias curl='~/.curl_with_pac.sh'
通过以上优化方案,我们可以让curl支持PAC自动代理,提高网络访问效率。