赞
踩
MacOS系统上,升级python3.12时,超级慢,而且最后还失败了。看了日志,发现是用curl从raw.githubusercontent.com上下载Python安装包超时了。
解决方案一:开启VPN工具,穿越围墙
解决方案二:使用raw.gitmirror.com替换raw.githubusercontent.com
穿墙有风险,操作需谨慎,这里我采用的是方案二。
1. 查看curl路径
- which curl
- # /usr/bin/curl
2. 编写自定义脚本,并赋予执行权限
- ln -s `which curl` /usr/local/bin/curl
- [ -d ~/.local/bin ] || mkdir -p ~/.local/bin/
- cd ~/.local/bin
- touch curl
- chmod +x curl
- # 注:PATH要配置到.bashrc或.zshrc里,别的窗口才能起作用
- export PATH=$HOME/.local/bin:$PATH
- vi curl
- which curl
- # ~/.local/bin/curl
3. 脚本内容
- #!/usr/bin/env python
- import os,sys
- origin,target="raw.githubusercontent.com","raw.gitmirror.com"
- args=" ".join(repr(i) if " " in i else i for i in sys.argv[1:])
- cmd="/usr/bin/{} ".format(sys.argv[0].split('/')[-1])+args.replace(origin,target)
- sys.exit(os.system(cmd))
4. 测试效果
curl https://raw.githubusercontent.com/Homebrew/homebrew-core/a775cbd0967da13128293d71fb26431fdedee6fb/Formula/m/mpdecimal.rb
5. 重新执行升级命令(这时候就很快了,不到一分钟就下载完毕,十分钟内就完成升级)
brew upgrade python@3.12
注: wget也可以用类似的方法加速
################# 2024.02.08 补充:
如果有外网服务器,还可以配个中转请求:
1. 本地curl文件内容如下(需export JUMPER_IP='<服务器IP地址>')
- #!/usr/bin/env python
- import os
- import sys
-
- try:
- from typing import List # NOQA:F401
- except ImportError:
- pass
-
-
- def gen_cmd(sys_argv):
- # type: (List[str]) -> str
- args = []
- scheme = "https://"
- origin, target = "raw.githubusercontent.com", "raw.gitmirror.com"
- domains = ("objects.githubusercontent.com", "github.com")
- redirect = os.getenv("JUMPER_IP")
- host = "http://{}:9337/".format(redirect)
- for i in sys_argv[1:]:
- if i.startswith(scheme):
- j = i[len(scheme) :]
- if j.startswith(origin):
- i = i.replace(origin, target)
- elif redirect:
- for domain in domains:
- if j.startswith(domain):
- i = host + j
- break
- elif " " in i:
- i = repr(i)
- args.append(i)
- tool = "/usr/local/bin/" + sys_argv[0].split("/")[-1]
- cmd = tool + " " + " ".join(args)
- return cmd
-
-
- def main():
- # type: () -> int
- sys_argv = sys.argv
- if "--dry" in sys_argv:
- sys_argv = [i for i in sys_argv if i != "--dry"]
- print("--> " + gen_cmd(sys_argv))
- return 0
- return os.system(gen_cmd(sys_argv))
-
-
- if __name__ == "__main__":
- sys.exit(main())
2. 服务器上的app.py文件如下:
- #!/usr/bin/env python
- import re
-
- # pip install httpx orjson loguru sanic gunicorn 'uvicorn[standard]'
- from httpx import AsyncClient
- from loguru import logger
- from orjson import dumps, loads
- from sanic import Sanic, raw
-
- app = Sanic("Jumper", dumps=dumps, loads=loads)
-
-
- @app.route("", methods=["GET", "POST", "PUT", "PATCH", "DELETE"])
- async def index(request):
- return raw(b"Welcome. Example>> http :8000/http.127.0.0.1:9000/home")
-
-
- @app.route("/<full:path>", methods=["GET", "POST", "PUT", "PATCH", "DELETE"])
- async def handler(request, full: str):
- host, url = full.lstrip("/"), ""
- if m := re.search(r"(https?)[^0-9a-zA-Z]+(.+)", host):
- scheme, host = m.groups()
- else:
- scheme = "https"
- try:
- domain, url = host.split("/", 1)
- except ValueError:
- domain = host
- base_url = scheme + "://" + domain
- target_path = url
- if qs := request.query_string:
- target_path += "?" + qs
- if not target_path:
- target_path = base_url
- if not target_path.startswith("/") and not target_path.startswith("http"):
- target_path = "/" + target_path
- logger.debug(f"{base_url=}; {target_path=}")
- async with AsyncClient(
- base_url=base_url, follow_redirects=True, timeout=20
- ) as client:
- method, body = request.method, request.body
- r = await client.request(method, target_path, content=body)
- if r.status_code == 302 and (next_url := r.headers.get("location")):
- r = await client.request(method, next_url, content=body)
- return raw(r.content, status=r.status_code)
-
-
- if __name__ == "__main__": # pragma: no cover
- app.run(debug=True, host="0.0.0.0")
3. 后台启动服务:
gunicorn app:app --bind 0.0.0.0:9337 --worker-class uvicorn.workers.UvicornWorker --daemon
4. 本地brew对应的install文件修改如下:
- cd $(brew --prefix)/Homebrew/Library/Homebrew
- grep -rn Downloading *.rb
- # download_strategy.rb:426:
- vi download_strategy.rb # 给download的url增加前缀
- git diff
增加这几行:
- if (domain = Homebrew::EnvConfig.artifact_domain)
- url = url.sub(%r{^https?://#{GitHubPackages::URL_DOMAIN}/}o, "#{domain.chomp("/")}/")
- + elsif url.start_with?("https://cdn.")
- + puts "Leave #{url} to be itself."
- + elsif !url.start_with?("https://mirrors.")
- + url = "http://your-server-ip-or-domain/" + url
- end
-
- ohai "Downloading #{url}"
即除了mirrors和cdn开头的域名,全都使用自建域名加速
- elsif url.start_with?("https://cdn.")
- puts "Leave #{url} to be itself."
- elsif !url.start_with?("https://mirrors.")
- url = "https://your.domain.com/" + url
################################
2024.03.06 补充
步骤4可以用如下Python脚本来实现:
- #!/usr/bin/env python
- """
- This script is used to improve download speed for `brew install`
- Usage::
- $ python pad_brew_download_url.py
- """
- import os
- import subprocess
-
- HOST = "https://xxx.com/" # 外网服务器对应的host(域名或IP地址)
- PAD = """
- elsif url.start_with?("https://cdn.")
- puts "Leave #{url} to be itself."
- elsif !url.start_with?("https://mirrors.")
- url = "%s" + url
- """
-
-
- def capture_output(cmd):
- # type: (str) -> str
- try:
- r = subprocess.run(cmd, shell=True, capture_output=True)
- except (TypeError, AttributeError): # For python<=3.6
- with os.popen(cmd) as p:
- return p.read().strip()
- else:
- return r.stdout.decode().strip()
-
-
- def main():
- # type: () -> None
- brew_root = capture_output("brew --prefix")
- folder = "Homebrew/Library/Homebrew"
- name = "download_strategy.rb"
- file = os.path.join(brew_root, folder, name)
- with open(file) as f:
- text = f.read()
- if HOST in text:
- print("{} already in {}\nNothing to do!".format(HOST, file))
- return
-
- s = ' end\n\n ohai "Downloading #{url}"'
- pad = PAD % HOST
- new_text = text.replace(s, pad.lstrip("\n") + s)
- with open(file, "w") as f:
- f.write(new_text)
- print("Insert {} into {}".format(pad, file))
-
-
- if __name__ == "__main__":
- main()
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。