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) } }