更新hosts加速 github 访问方案 程序代码
参考:
国内加速访问Github的办法,超级简单 - 扩展迷Extfans的文章 - 知乎
https://zhuanlan.zhihu.com/p/65154116
手动改来改去太麻烦了,于是写了个 Go 程序来自动更新。
/***************************************************************************** 文件: github_hosts_speed.go 描述: 获取 github 相关域名的 ip 地址 作者: solym ymwh@foxmail.com 版本: 2020.04.27 日期: 2020年4月27日 历史: *****************************************************************************/ package main import ( "bufio" "bytes" "fmt" "io/ioutil" "net/http" "os" "runtime" json "github.com/json-iterator/go" ) func httpGetRequest(url string) ([]byte, error) { // 创建一个请求 req, err := http.NewRequest("GET", url, nil) if err != nil { return nil, err } // 设置头,模拟火狐浏览器 req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:75.0) Gecko/20100101 Firefox/75.0") req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8") req.Header.Set("Accept-Language", "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2") req.Header.Set("Connection", "keep-alive") req.Header.Set("Upgrade-Insecure-Requests", "1") req.Header.Set("Pragma", "no-cache") req.Header.Set("Cache-Control", "no-cache") // 执行请求结果 resp, err := http.DefaultClient.Do(req) if err != nil { return nil, err } defer resp.Body.Close() // 获取返回结果 data, err := ioutil.ReadAll(resp.Body) if resp.StatusCode != 200 || err != nil { return nil, fmt.Errorf("请求失败:[%d] %v", resp.StatusCode, err) } return data, nil } func getPublicIP() (string, error) { // 通过访问 http://pv.sohu.com/cityjson 来获取 // var returnCitySN = {"cip": "111.196.240.67", "cid": "110000", "cname": "北京市"}; data, err := httpGetRequest("http://pv.sohu.com/cityjson") if err != nil { return "", err } if i := bytes.IndexByte(data, '{'); i > 0 { data = data[i:] any := json.Get(data, "cip") return any.ToString(), nil } else { return "", fmt.Errorf("格式不正确:%s", string(data)) } } func getIPAddressOfDomain(domain, myip string) (string, error) { /* // 通过 119.29.29.29 的 接口获取最合适的 IP url := "http://119.29.29.29/d?dn=" + domain + "&ip=" + myip data, err := httpGetRequest(url) if err != nil { return "", err } // 可能会有多个 IP 返回,只要第一个 // 185.199.109.154;185.199.110.154;185.199.111.154;185.199.108.154 if i := bytes.IndexByte(data, ';'); i > 6 { data = data[0:i] } return string(data), nil */ // 通过 https://github.com.ipaddress.com/gist.github.com 获取 primarydomain := domain if domainpart := strings.Split(primarydomain, "."); len(domainpart) > 2 { primarydomain = domainpart[len(domainpart)-2] + "." + domainpart[len(domainpart)-1] } // if d1 := strings.LastIndex(primarydomain, "."); d1 > 0 { // if d1 := strings.LastIndex(primarydomain[:d1-1], "."); d1 > 0 { // primarydomain = primarydomain[d1+1:] // } // } url := "https://" + primarydomain + ".ipaddress.com/" + domain data, err := httpGetRequest(url) if err != nil { return "", err } // <a href="https://www.ipaddress.com/ipv4/140.82.112.4">140.82.112.4</a> sep := []byte("<a href=\"https://www.ipaddress.com/ipv4/") if i := bytes.Index(data, sep); i > 0 { data = data[i+len(sep):] if j := bytes.Index(data, []byte("\">")); j > 0 { return string(data[:j]), nil } } return "", fmt.Errorf("获取IP失败:%s", domain) } func main() { // 1、获取本机的公网IP myip, err := getPublicIP() if err != nil { fmt.Println("获取公网 IP 地址失败:", err) return } // 2、获取域名对应的IP地址 domainlist := []string{ "github.global.ssl.fastly.net", "github.com", "assets-cdn.github.com", "documentcloud.github.com", "gist.github.com", "help.github.com", "nodeload.github.com", "raw.github.com", "status.github.com", "training.github.com", "www.github.com", "avatars0.githubusercontent.com", "avatars1.githubusercontent.com", "github.githubassets.com", "github-production-release-asset-2e65be.s3.amazonaws.com", "api.github.com", "user-images.githubusercontent.com", "raw.githubusercontent.com", "gist.githubusercontent.com", "camo.githubusercontent.com", "avatars2.githubusercontent.com", "avatars3.githubusercontent.com", "avatars4.githubusercontent.com", "avatars5.githubusercontent.com", "avatars6.githubusercontent.com", "avatars8.githubusercontent.com", "github.io", "avatars7.githubusercontent.com", } // 域名IP映射表 domaintoipaddr := make(map[string]string) for _, domain := range domainlist { ipaddr, err := getIPAddressOfDomain(domain, myip) if err != nil { fmt.Println("错误:", err, domain) continue } fmt.Println(ipaddr, domain) domaintoipaddr[domain] = ipaddr } // 3、更新 hosts 文件 hostspath := "/etc/hosts" if runtime.GOOS == "windows" { // 这里应该先通过环境变量 windir 或 SystemRoot 获取路径 hostspath = "C:/Windows/System32/drivers/etc/hosts" } // 读取 hosts 文件 hostsdata, err := ioutil.ReadFile(hostspath) if err != nil { fmt.Println(err) return } // 逐行读取并更新 hostsreader := bufio.NewReader(bytes.NewReader(hostsdata)) hostsbuffer := bytes.NewBuffer(nil) hostswriter := bufio.NewWriter(hostsbuffer) line, err := hostsreader.ReadSlice('\n') for ; err == nil; line, err = hostsreader.ReadSlice('\n') { // 分割为多个部分 fields := bytes.Fields(line) // 可能是 # xxx xxxx // 127.0.0.1 localhost # xxxxx // 等多种形势 if len(fields) < 2 || fields[0][0] == byte('#') { hostswriter.Write(line) continue } // 如果域名存在,则替换 domain := string(fields[1]) if ipaddr, ok := domaintoipaddr[domain]; ok { fields[0] = []byte(ipaddr) line = bytes.Join(fields, []byte(" ")) line = append(line, byte('\n')) // 将映射表内的删除 delete(domaintoipaddr, domain) } hostswriter.Write(line) } // 将不存在 Hosts 中的加入 hostswriter.WriteString("\n# github speed\n") for domain := range domaintoipaddr { hostswriter.WriteString(fmt.Sprintln(domaintoipaddr[domain], domain)) } hostswriter.Flush() // 写入到 hosts 文件,这里应该需要管理员权限 err = ioutil.WriteFile(hostspath, hostsbuffer.Bytes(), os.ModePerm) if err != nil { fmt.Println("写入更新失败:", err) return } // 还需要刷新下 DNS 缓存,这里就直接给个提示好了 fmt.Println("更新 hosts 文件完成,需要刷新 DNS 缓存请参考下面命令") fmt.Println("Windows 请执行命令: ipconfig /flushdns") fmt.Println("Linux 请执行命令: sudo service nscd restart") fmt.Println(" 或: sudo service restart") fmt.Println(" 或: sudo systemctl restart network") fmt.Println(" 或: sudo /etc/init.d/networking restart") fmt.Println("MacOS 请执行命令: sudo killall -HUP mDNSResponder") fmt.Println(" Yosemite: sudo discoveryutil udnsflushcaches") fmt.Println(" Snow Leopard: sudo dscacheutil -flushcache") fmt.Println("Leopard and below: sudo lookupd -flushcache") }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
2017-04-27 Qt Installer Framework 使用说明(三)
2017-04-27 Qt Installer Framework 使用说明(二)
2017-04-27 Qt Installer Framework 使用说明(一)