Golang定期检查端口上的开放TCP连接。

huangapple go评论110阅读模式
英文:

Golang periodically checking open TCP connections at a port

问题

我正在尝试编写一个小的Go程序,它会定期执行lsof -i:<port>命令,以检查端口上打开的TCP连接数。代码如下所示:

  1. package main
  2. import (
  3. "fmt"
  4. "log"
  5. "os/exec"
  6. "strings"
  7. "sync"
  8. "time"
  9. )
  10. type Lsof struct {
  11. Command string
  12. Pid string
  13. User string
  14. Fd string
  15. Type string
  16. Device string
  17. SizeOff string
  18. Node string
  19. Name string
  20. TCPState string
  21. }
  22. //var result = make([]*Lsof, 0)
  23. var ports = []int{30001, 30002}
  24. func main() {
  25. done := make(chan bool)
  26. ticker := time.NewTicker(5 * time.Millisecond)
  27. go func() {
  28. for t := range ticker.C {
  29. fmt.Println("Tick at", t)
  30. connectionsCount()
  31. }
  32. }()
  33. <-done
  34. }
  35. func connectionsCount() {
  36. var wg sync.WaitGroup
  37. wg.Add(len(ports))
  38. for _, v := range ports {
  39. go count(v, wg)
  40. }
  41. wg.Wait()
  42. }
  43. func count(port int, wg sync.WaitGroup) {
  44. defer wg.Done()
  45. var tcpState = make(map[string]int)
  46. out, err := exec.Command("/bin/sh", "-c", fmt.Sprintf("lsof -i:%d", port)).Output()
  47. if err != nil {
  48. log.Fatal(err)
  49. }
  50. //fmt.Println(string(out))
  51. num := strings.Split(string(out), "\n")
  52. for no, n := range num {
  53. if no == 0 {
  54. continue
  55. }
  56. n = strings.TrimSpace(n)
  57. if len(n) <= 0 {
  58. continue
  59. }
  60. i := 0
  61. temp := strings.Split(n, " ")
  62. cleanedVal := make([]string, 10)
  63. for _, v := range temp {
  64. v = strings.TrimSpace(v)
  65. if len(v) <= 0 {
  66. continue
  67. }
  68. cleanedVal[i] = v
  69. i++
  70. }
  71. if len(cleanedVal) < 8 {
  72. //log.Println(n)
  73. continue
  74. }
  75. l := new(Lsof)
  76. l.Command = cleanedVal[0]
  77. l.Pid = cleanedVal[1]
  78. l.User = cleanedVal[2]
  79. l.Fd = cleanedVal[3]
  80. l.Type = cleanedVal[4]
  81. l.Device = cleanedVal[5]
  82. l.SizeOff = cleanedVal[6]
  83. l.Node = cleanedVal[7]
  84. l.Name = cleanedVal[8]
  85. if l.Node == "TCP" {
  86. l.TCPState = cleanedVal[9]
  87. count, ok := tcpState[l.TCPState]
  88. if !ok {
  89. tcpState[l.TCPState] = 1
  90. } else {
  91. tcpState[l.TCPState] = count + 1
  92. }
  93. }
  94. //fmt.Printf("\n%+v", *l)
  95. //result = append(result, l)
  96. }
  97. fmt.Printf("Port=%d ", port)
  98. for k, v := range tcpState {
  99. fmt.Printf("{TCP State=%s,Value=%d},", k, v)
  100. }
  101. fmt.Println()
  102. }

但是运行程序后,我发现定时器没有按预期定时触发。

  1. Tick at 2016-12-21 14:37:03.847694697 +0530 IST
  2. Port=30002 {TCP State=(LISTEN),Value=2},
  3. Port=30001 {TCP State=(LISTEN),Value=2},

有人能告诉我出了什么问题吗?

  • Go版本-1.7.3
英文:

I am trying write a small golang program which will periodically execute lsof -i:&lt;port&gt; to check number of open TCP connections at a port. Code looks like below:-

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;log&quot;
  5. &quot;os/exec&quot;
  6. &quot;strings&quot;
  7. &quot;sync&quot;
  8. &quot;time&quot;
  9. )
  10. type Lsof struct {
  11. Command string
  12. Pid string
  13. User string
  14. Fd string
  15. Type string
  16. Device string
  17. SizeOff string
  18. Node string
  19. Name string
  20. TCPState string
  21. }
  22. //var result = make([]*Lsof, 0)
  23. var ports = []int{30001, 30002}
  24. func main() {
  25. done := make(chan bool)
  26. ticker := time.NewTicker(5 * time.Millisecond)
  27. go func() {
  28. for t := range ticker.C {
  29. fmt.Println(&quot;Tick at&quot;, t)
  30. connectionsCount()
  31. }
  32. }()
  33. &lt;-done
  34. }
  35. func connectionsCount() {
  36. var wg sync.WaitGroup
  37. wg.Add(len(ports))
  38. for _, v := range ports {
  39. go count(v, wg)
  40. }
  41. wg.Wait()
  42. }
  43. func count(port int, wg sync.WaitGroup) {
  44. defer wg.Done()
  45. var tcpState = make(map[string]int)
  46. out, err := exec.Command(&quot;/bin/sh&quot;, &quot;-c&quot;, fmt.Sprintf(&quot;lsof -i:%d&quot;, port)).Output()
  47. if err != nil {
  48. log.Fatal(err)
  49. }
  50. //fmt.Println(string(out))
  51. num := strings.Split(string(out), &quot;\n&quot;)
  52. for no, n := range num {
  53. if no == 0 {
  54. continue
  55. }
  56. n = strings.TrimSpace(n)
  57. if len(n) &lt;= 0 {
  58. continue
  59. }
  60. i := 0
  61. temp := strings.Split(n, &quot; &quot;)
  62. cleanedVal := make([]string, 10)
  63. for _, v := range temp {
  64. v = strings.TrimSpace(v)
  65. if len(v) &lt;= 0 {
  66. continue
  67. }
  68. cleanedVal[i] = v
  69. i++
  70. }
  71. if len(cleanedVal) &lt; 8 {
  72. //log.Println(n)
  73. continue
  74. }
  75. l := new(Lsof)
  76. l.Command = cleanedVal[0]
  77. l.Pid = cleanedVal[1]
  78. l.User = cleanedVal[2]
  79. l.Fd = cleanedVal[3]
  80. l.Type = cleanedVal[4]
  81. l.Device = cleanedVal[5]
  82. l.SizeOff = cleanedVal[6]
  83. l.Node = cleanedVal[7]
  84. l.Name = cleanedVal[8]
  85. if l.Node == &quot;TCP&quot; {
  86. l.TCPState = cleanedVal[9]
  87. count, ok := tcpState[l.TCPState]
  88. if !ok {
  89. tcpState[l.TCPState] = 1
  90. } else {
  91. tcpState[l.TCPState] = count + 1
  92. }
  93. }
  94. //fmt.Printf(&quot;\n%+v&quot;, *l)
  95. //result = append(result, l)
  96. }
  97. fmt.Printf(&quot;Port=%d &quot;, port)
  98. for k, v := range tcpState {
  99. fmt.Printf(&quot;{TCP State=%s,Value=%d},&quot;, k, v)
  100. }
  101. fmt.Println()
  102. }

But on running the program I am seeing the ticker is not ticking periodically.

  1. Tick at 2016-12-21 14:37:03.847694697 +0530 IST
  2. Port=30002 {TCP State=(LISTEN),Value=2},
  3. Port=30001 {TCP State=(LISTEN),Value=2},

Can someone let me know what is going wrong?

  • Go Version - 1.7.3

答案1

得分: 3

这里的问题不在于 Ticker,尝试使用以下代码:

  1. for t := range ticker.C {
  2. fmt.Println("Tick at", t)
  3. // connectionsCount()
  4. }

不要通过值传递 WaitGroup。将 wg 作为指针传递将解决该问题。函数一直在等待。

将其更新为:

  1. ......
  2. func connectionsCount() {
  3. var wg = &sync.WaitGroup{}
  4. wg.Add(len(ports))
  5. for _, v := range ports {
  6. go count(v, wg)
  7. }
  8. wg.Wait()
  9. }
  10. func count(port int, wg *sync.WaitGroup) {
  11. .......

这是播放链接:链接

英文:

Here the issue is not with the Ticker
try

  1. for t := range ticker.C {
  2. fmt.Println(&quot;Tick at&quot;, t)
  3. // connectionsCount()
  4. }

You shall not pass WaitGroup by value . Passing wg as pointer will solve the issue. The fuction was waiting for ever

update it to

  1. .....
  2. func connectionsCount() {
  3. var wg = &amp;sync.WaitGroup{}
  4. wg.Add(len(ports))
  5. for _, v := range ports {
  6. go count(v, wg)
  7. }
  8. wg.Wait()
  9. }
  10. func count(port int, wg *sync.WaitGroup) {
  11. .......

Here is the play link

huangapple
  • 本文由 发表于 2016年12月21日 17:25:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/41259191.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定