zoukankan      html  css  js  c++  java
  • 更新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('
    ')
    	for ; err == nil; line, err = hostsreader.ReadSlice('
    ') {
    		// 分割为多个部分
    		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('
    '))
    			// 将映射表内的删除
    			delete(domaintoipaddr, domain)
    		}
    		hostswriter.Write(line)
    	}
    	// 将不存在 Hosts 中的加入
    	hostswriter.WriteString("
    # github speed
    ")
    	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")
    }
    
  • 相关阅读:
    Shell学习笔记 ——第一天
    Myclipse 安装 Maven遇见的N个异常
    Myeclipse 创建 Web Maven项目
    Guava API
    String 转Map(基于Guava类库)
    Mybatis——helloWorld级程序
    redis
    listener、context、filter、servlet及其加载顺序
    junit 单元测试
    hibernate —— 树状存储
  • 原文地址:https://www.cnblogs.com/oloroso/p/12789641.html
Copyright © 2011-2022 走看看