|
@@ -0,0 +1,155 @@
|
|
|
+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)
|
|
|
+ }
|
|
|
+}
|