main.go 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package main
  2. import (
  3. "bytes"
  4. "os/exec"
  5. "strings"
  6. "time"
  7. )
  8. const (
  9. pingInterval = 60 * time.Second // 每10秒执行一次
  10. ipToPing = "203.34.49.130" // 这里填写要ping的IP地址
  11. )
  12. // checkErr 输出错误信息并退出程序
  13. func checkErr(err error) {
  14. if err != nil {
  15. //log.Fatalf("Error: %s", err)
  16. }
  17. }
  18. // ping 检查是否可以到达指定的IP地址
  19. func ping(ip string) bool {
  20. cmd := exec.Command("ping", "-c", "1", ip)
  21. var out bytes.Buffer
  22. cmd.Stdout = &out
  23. err := cmd.Run()
  24. output := out.String()
  25. if strings.Contains(output, "1 packets transmitted, 1 received") ||
  26. strings.Contains(output, "1 packets transmitted, 1 received, 0% packet loss") {
  27. return true
  28. }
  29. return err == nil
  30. }
  31. // checkNet 解析ip route命令的输出,返回接口与默认网关的映射以及当前默认网卡名
  32. func checkNet(net string) (map[string]string, string) {
  33. var defaultNet string
  34. m := make(map[string]string)
  35. split := strings.Split(net, "\n")
  36. for i := 0; i < len(split)-1; i++ {
  37. line := strings.TrimSpace(split[i])
  38. if line == "" {
  39. continue
  40. }
  41. defaultNets := strings.Fields(line)
  42. if len(defaultNets) > 1 {
  43. for k := 0; k < len(defaultNets)-1; k++ {
  44. if defaultNets[k] == "dev" && defaultNets[0] == "default" {
  45. defaultNet = defaultNets[k+1]
  46. }
  47. }
  48. }
  49. i2 := strings.Fields(line)
  50. if len(i2) > 1 {
  51. for j := 0; j < len(i2)-1; j++ {
  52. if i2[j] == "dev" {
  53. netName := i2[j+1]
  54. i3 := strings.Split(i2[j-1], ".")
  55. if len(i3) > 1 {
  56. ip := i3[0] + "." + i3[1] + "." + i3[2] + ".1"
  57. m[netName] = ip
  58. }
  59. }
  60. }
  61. }
  62. }
  63. //fmt.Println("Routes:", m)
  64. //fmt.Println("Default Net:", defaultNet)
  65. return m, defaultNet
  66. }
  67. // updateRoute 更新默认路由
  68. func updateRoute(routes map[string]string, currentDefault, newDefault string) {
  69. if currentDefault != newDefault {
  70. cmdDel := exec.Command("ip", "route", "del", "default", "via", routes[currentDefault], "dev", currentDefault)
  71. cmdAdd := exec.Command("ip", "route", "add", "default", "via", routes[newDefault], "dev", newDefault)
  72. checkErr(cmdDel.Run())
  73. checkErr(cmdAdd.Run())
  74. //fmt.Printf("切换默认网卡 从 %s 到 %s\n", currentDefault, newDefault)
  75. } else {
  76. //fmt.Println("不需要切换默认网卡")
  77. }
  78. }
  79. func main() {
  80. for {
  81. b := ping(ipToPing)
  82. if b {
  83. //fmt.Println("网络连接正常")
  84. // 获取所有可用的网络接口及其默认网关
  85. cmd := exec.Command("ip", "route")
  86. var out bytes.Buffer
  87. cmd.Stdout = &out
  88. checkErr(cmd.Run())
  89. output := out.String()
  90. routes, currentDefault := checkNet(output)
  91. // 判断当前默认网卡是否为 eth 网卡
  92. if !strings.Contains(currentDefault, "eth") {
  93. //fmt.Println("当前为无线网卡,正在切换到有线网卡")
  94. for k := range routes {
  95. if strings.Contains(k, "eth") {
  96. updateRoute(routes, currentDefault, k)
  97. break
  98. }
  99. }
  100. } else {
  101. //fmt.Println("当前为有线网卡,无需切换")
  102. }
  103. } else {
  104. //fmt.Println("网络未接通正在重启....")
  105. // 获取所有可用的网络接口及其默认网关
  106. cmd := exec.Command("ip", "route")
  107. var out bytes.Buffer
  108. cmd.Stdout = &out
  109. checkErr(cmd.Run())
  110. output := out.String()
  111. routes, currentDefault := checkNet(output)
  112. // 找到一个新的默认网卡
  113. newDefault := ""
  114. for k := range routes {
  115. if k != currentDefault {
  116. newDefault = k
  117. break
  118. }
  119. }
  120. if newDefault != "" {
  121. updateRoute(routes, currentDefault, newDefault)
  122. // 再次检查是否可以 ping 通
  123. b := ping(ipToPing)
  124. if b {
  125. //fmt.Println("切换网卡后网络连接正常")
  126. } else {
  127. //fmt.Println("切换网卡后仍然无法 ping 通")
  128. }
  129. } else {
  130. //fmt.Println("没有找到其他可用的网卡")
  131. }
  132. }
  133. time.Sleep(pingInterval)
  134. }
  135. }