eth0net.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package netmgrd
  2. import (
  3. "fmt"
  4. "net"
  5. "os"
  6. "os/exec"
  7. "strconv"
  8. "strings"
  9. "syscall"
  10. "time"
  11. "github.com/sirupsen/logrus"
  12. "hnyfkj.com.cn/rtu/linux/baseapp"
  13. )
  14. // 只保留需要使用的"eth0"网卡
  15. func disableEthBut0() error {
  16. ifaces, err := net.Interfaces()
  17. if err != nil {
  18. return fmt.Errorf("获取网络接口列表失败: %w", err)
  19. }
  20. for _, iface := range ifaces {
  21. if !strings.HasPrefix(iface.Name, "eth") || iface.Name == "eth0" {
  22. continue
  23. }
  24. cmd := exec.Command("ip", "link", "set", "dev", iface.Name, "down")
  25. cmd.Stdout = baseapp.Logger.WriterLevel(logrus.DebugLevel)
  26. cmd.Stderr = baseapp.Logger.WriterLevel(logrus.ErrorLevel)
  27. if err := cmd.Run(); err != nil {
  28. return fmt.Errorf("关闭网口\"%s\"失败: %w", iface.Name, err)
  29. }
  30. }
  31. return nil
  32. }
  33. // 启动DHCP客户端, 请求IP地址
  34. func dialupEth0() error {
  35. cmd1 := exec.Command("ip", "link", "set", "dev", "eth0", "up")
  36. cmd1.Stdout = baseapp.Logger.WriterLevel(logrus.DebugLevel)
  37. cmd1.Stderr = baseapp.Logger.WriterLevel(logrus.ErrorLevel)
  38. if err := cmd1.Run(); err != nil {
  39. return fmt.Errorf("启动网口\"eth0\"失败: %w", err)
  40. }
  41. eth2pid := baseapp.RUN_DIR + "/udhcpc.eth0.pid"
  42. cmd2 := exec.Command("udhcpc", "-b", "-i", "eth0", "-p", eth2pid)
  43. cmd2.Stdout = baseapp.Logger.WriterLevel(logrus.DebugLevel)
  44. cmd2.Stderr = baseapp.Logger.WriterLevel(logrus.ErrorLevel)
  45. if err := cmd2.Run(); err != nil {
  46. return fmt.Errorf("\"eth0\"请求地址失败: %w", err)
  47. }
  48. return nil
  49. }
  50. // 检测"eth0"网口上的"udhcpc"后台进程是否正在运行, 只保持一个实例
  51. func udhcpcEth0Exists() (bool, error) {
  52. eth2pid := baseapp.RUN_DIR + "/udhcpc.eth0.pid"
  53. data, err := os.ReadFile(eth2pid)
  54. if err != nil {
  55. return false, err
  56. }
  57. pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
  58. if err != nil {
  59. return false, err
  60. }
  61. err = syscall.Kill(pid, 0)
  62. if err == nil { // 存在
  63. return true, nil
  64. }
  65. if err == syscall.ESRCH { // 不存在
  66. return false, nil
  67. }
  68. return false, err
  69. }
  70. // 杀死"eth0"网口上的"udhcpc"进程(根据上次运行时它的PID-文件记录)
  71. func KillEth0Udhcpc() error {
  72. eth2pid := baseapp.RUN_DIR + "/udhcpc.eth0.pid"
  73. data, err := os.ReadFile(eth2pid)
  74. if err != nil {
  75. return err
  76. }
  77. pid, err := strconv.Atoi(strings.TrimSpace(string(data)))
  78. if err != nil {
  79. return err
  80. }
  81. if err := syscall.Kill(pid, syscall.SIGTERM); err != nil && err != syscall.ESRCH {
  82. syscall.Kill(pid, syscall.SIGKILL)
  83. }
  84. return nil
  85. }
  86. // 强制杀死所有运行中的"udhcpc"进程,包括驻留在后台运行的(SIGKILL)
  87. func killAllUdhcpc() {
  88. cmd := exec.Command("sh", "-c", `ps | grep '[u]dhcpc' | awk '{print $1}'`)
  89. output, err := cmd.Output()
  90. if err != nil {
  91. return // 没找到也不是错误
  92. }
  93. pids := strings.FieldsSeq(string(output))
  94. for pidStr := range pids {
  95. pid, err := strconv.Atoi(pidStr)
  96. if err != nil {
  97. continue
  98. }
  99. if err := syscall.Kill(pid, syscall.SIGTERM); err != nil && err != syscall.ESRCH {
  100. syscall.Kill(pid, syscall.SIGKILL)
  101. }
  102. }
  103. }
  104. // 运行"udhcpc"后, 获取"eth0"网口分配到的IPv4地址, 并校检其合法性
  105. func getEth0Addr() (ip, mask string, err error) {
  106. iface, err := net.InterfaceByName("eth0")
  107. if err != nil {
  108. return "", "", fmt.Errorf("找不到网络接口\"eth0\": %w", err)
  109. }
  110. addrs, err := iface.Addrs()
  111. if err != nil {
  112. return "", "", fmt.Errorf("获取\"eth0\"的地址失败: %w", err)
  113. }
  114. for _, addr := range addrs {
  115. ipNet, ok := addr.(*net.IPNet)
  116. if !ok {
  117. continue
  118. }
  119. ip4 := ipNet.IP.To4()
  120. if ip4 == nil {
  121. continue
  122. }
  123. if ip4.IsPrivate() { // 判断得到IP地址是否合法
  124. return ip4.String(), net.IP(ipNet.Mask).String(), nil
  125. } else {
  126. return "", "", fmt.Errorf("分配给\"eth0\"的地址\"%s\"无效", ip4.String())
  127. }
  128. }
  129. return "", "", fmt.Errorf("在\"eth0\"上未找到有效的IPv4 地址")
  130. }
  131. // 定时检测"eth0"网卡上的"udhcpc"后台服务进程, 发现退出时自动拉起
  132. func MonitorEth0Udhcpc(exitCh <-chan struct{}) {
  133. t := time.NewTicker(time.Duration(5) * time.Second)
  134. defer t.Stop()
  135. for {
  136. select {
  137. case <-t.C:
  138. bExists, _ := udhcpcEth0Exists()
  139. if !bExists { // 清场一次
  140. killAllUdhcpc()
  141. disableEthBut0()
  142. }
  143. if !bExists && dialupEth0() == nil { // 重新进场
  144. ip, mask, _ := getEth0Addr()
  145. baseapp.Logger.Warnf("[%s] \"eth0\"重新分配的地址: %s/%s!", MODULE_NAME, ip, mask)
  146. }
  147. case <-exitCh:
  148. return
  149. } // select end
  150. } // for end
  151. }