123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- package main
- import (
- "bytes"
- "os/exec"
- "strings"
- "time"
- )
- const (
- pingInterval = 60 * time.Second // 每10秒执行一次
- ipToPing = "203.34.49.130" // 这里填写要ping的IP地址
- )
- // checkErr 输出错误信息并退出程序
- func checkErr(err error) {
- if err != nil {
- //log.Fatalf("Error: %s", err)
- }
- }
- // ping 检查是否可以到达指定的IP地址
- func ping(ip string) bool {
- cmd := exec.Command("ping", "-c", "1", ip)
- var out bytes.Buffer
- cmd.Stdout = &out
- err := cmd.Run()
- output := out.String()
- if strings.Contains(output, "1 packets transmitted, 1 received") ||
- strings.Contains(output, "1 packets transmitted, 1 received, 0% packet loss") {
- return true
- }
- return err == nil
- }
- // checkNet 解析ip route命令的输出,返回接口与默认网关的映射以及当前默认网卡名
- func checkNet(net string) (map[string]string, string) {
- var defaultNet string
- m := make(map[string]string)
- split := strings.Split(net, "\n")
- for i := 0; i < len(split)-1; i++ {
- line := strings.TrimSpace(split[i])
- if line == "" {
- continue
- }
- defaultNets := strings.Fields(line)
- if len(defaultNets) > 1 {
- for k := 0; k < len(defaultNets)-1; k++ {
- if defaultNets[k] == "dev" && defaultNets[0] == "default" {
- defaultNet = defaultNets[k+1]
- }
- }
- }
- i2 := strings.Fields(line)
- if len(i2) > 1 {
- for j := 0; j < len(i2)-1; j++ {
- if i2[j] == "dev" {
- netName := i2[j+1]
- i3 := strings.Split(i2[j-1], ".")
- if len(i3) > 1 {
- ip := i3[0] + "." + i3[1] + "." + i3[2] + ".1"
- m[netName] = ip
- }
- }
- }
- }
- }
- //fmt.Println("Routes:", m)
- //fmt.Println("Default Net:", defaultNet)
- return m, defaultNet
- }
- // updateRoute 更新默认路由
- func updateRoute(routes map[string]string, currentDefault, newDefault string) {
- if currentDefault != newDefault {
- cmdDel := exec.Command("ip", "route", "del", "default", "via", routes[currentDefault], "dev", currentDefault)
- cmdAdd := exec.Command("ip", "route", "add", "default", "via", routes[newDefault], "dev", newDefault)
- checkErr(cmdDel.Run())
- checkErr(cmdAdd.Run())
- //fmt.Printf("切换默认网卡 从 %s 到 %s\n", currentDefault, newDefault)
- } else {
- //fmt.Println("不需要切换默认网卡")
- }
- }
- func main() {
- for {
- b := ping(ipToPing)
- if b {
- //fmt.Println("网络连接正常")
- // 获取所有可用的网络接口及其默认网关
- cmd := exec.Command("ip", "route")
- var out bytes.Buffer
- cmd.Stdout = &out
- checkErr(cmd.Run())
- output := out.String()
- routes, currentDefault := checkNet(output)
- // 判断当前默认网卡是否为 eth 网卡
- if !strings.Contains(currentDefault, "eth") {
- //fmt.Println("当前为无线网卡,正在切换到有线网卡")
- for k := range routes {
- if strings.Contains(k, "eth") {
- updateRoute(routes, currentDefault, k)
- break
- }
- }
- } else {
- //fmt.Println("当前为有线网卡,无需切换")
- }
- } else {
- //fmt.Println("网络未接通正在重启....")
- // 获取所有可用的网络接口及其默认网关
- cmd := exec.Command("ip", "route")
- var out bytes.Buffer
- cmd.Stdout = &out
- checkErr(cmd.Run())
- output := out.String()
- routes, currentDefault := checkNet(output)
- // 找到一个新的默认网卡
- newDefault := ""
- for k := range routes {
- if k != currentDefault {
- newDefault = k
- break
- }
- }
- if newDefault != "" {
- updateRoute(routes, currentDefault, newDefault)
- // 再次检查是否可以 ping 通
- b := ping(ipToPing)
- if b {
- //fmt.Println("切换网卡后网络连接正常")
- } else {
- //fmt.Println("切换网卡后仍然无法 ping 通")
- }
- } else {
- //fmt.Println("没有找到其他可用的网卡")
- }
- }
- time.Sleep(pingInterval)
- }
- }
|