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

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

Golang periodically checking open TCP connections at a port

问题

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

package main

import (
	"fmt"
	"log"
	"os/exec"
	"strings"
	"sync"
	"time"
)

type Lsof struct {
	Command  string
	Pid      string
	User     string
	Fd       string
	Type     string
	Device   string
	SizeOff  string
	Node     string
	Name     string
	TCPState string
}

//var result = make([]*Lsof, 0)
var ports = []int{30001, 30002}

func main() {
	done := make(chan bool)
	ticker := time.NewTicker(5 * time.Millisecond)
	go func() {
		for t := range ticker.C {
			fmt.Println("Tick at", t)
			connectionsCount()
		}
	}()
	<-done
}

func connectionsCount() {
	var wg sync.WaitGroup
	wg.Add(len(ports))
	for _, v := range ports {
		go count(v, wg)
	}
	wg.Wait()
}

func count(port int, wg sync.WaitGroup) {
	defer wg.Done()
	var tcpState = make(map[string]int)
	out, err := exec.Command("/bin/sh", "-c", fmt.Sprintf("lsof -i:%d", port)).Output()
	if err != nil {
		log.Fatal(err)
	}
	//fmt.Println(string(out))
	num := strings.Split(string(out), "\n")
	for no, n := range num {
		if no == 0 {
			continue
		}
		n = strings.TrimSpace(n)
		if len(n) <= 0 {
			continue
		}
		i := 0
		temp := strings.Split(n, " ")
		cleanedVal := make([]string, 10)
		for _, v := range temp {
			v = strings.TrimSpace(v)
			if len(v) <= 0 {
				continue
			}
			cleanedVal[i] = v
			i++
		}
		if len(cleanedVal) < 8 {
			//log.Println(n)
			continue
		}
		l := new(Lsof)
		l.Command = cleanedVal[0]
		l.Pid = cleanedVal[1]
		l.User = cleanedVal[2]
		l.Fd = cleanedVal[3]
		l.Type = cleanedVal[4]
		l.Device = cleanedVal[5]
		l.SizeOff = cleanedVal[6]
		l.Node = cleanedVal[7]
		l.Name = cleanedVal[8]
		if l.Node == "TCP" {
			l.TCPState = cleanedVal[9]
			count, ok := tcpState[l.TCPState]
			if !ok {
				tcpState[l.TCPState] = 1
			} else {
				tcpState[l.TCPState] = count + 1
			}
		}
		//fmt.Printf("\n%+v", *l)
		//result = append(result, l)
	}
	fmt.Printf("Port=%d ", port)
	for k, v := range tcpState {
		fmt.Printf("{TCP State=%s,Value=%d},", k, v)
	}
	fmt.Println()
}

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

Tick at 2016-12-21 14:37:03.847694697 +0530 IST
Port=30002 {TCP State=(LISTEN),Value=2},
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:-

package main
import (
&quot;fmt&quot;
&quot;log&quot;
&quot;os/exec&quot;
&quot;strings&quot;
&quot;sync&quot;
&quot;time&quot;
)
type Lsof struct {
Command  string
Pid      string
User     string
Fd       string
Type     string
Device   string
SizeOff  string
Node     string
Name     string
TCPState string
}
//var result = make([]*Lsof, 0)
var ports = []int{30001, 30002}
func main() {
done := make(chan bool)
ticker := time.NewTicker(5 * time.Millisecond)
go func() {
for t := range ticker.C {
fmt.Println(&quot;Tick at&quot;, t)
connectionsCount()
}
}()
&lt;-done
}
func connectionsCount() {
var wg sync.WaitGroup
wg.Add(len(ports))
for _, v := range ports {
go count(v, wg)
}
wg.Wait()
}
func count(port int, wg sync.WaitGroup) {
defer wg.Done()
var tcpState = make(map[string]int)
out, err := exec.Command(&quot;/bin/sh&quot;, &quot;-c&quot;, fmt.Sprintf(&quot;lsof -i:%d&quot;, port)).Output()
if err != nil {
log.Fatal(err)
}
//fmt.Println(string(out))
num := strings.Split(string(out), &quot;\n&quot;)
for no, n := range num {
if no == 0 {
continue
}
n = strings.TrimSpace(n)
if len(n) &lt;= 0 {
continue
}
i := 0
temp := strings.Split(n, &quot; &quot;)
cleanedVal := make([]string, 10)
for _, v := range temp {
v = strings.TrimSpace(v)
if len(v) &lt;= 0 {
continue
}
cleanedVal[i] = v
i++
}
if len(cleanedVal) &lt; 8 {
//log.Println(n)
continue
}
l := new(Lsof)
l.Command = cleanedVal[0]
l.Pid = cleanedVal[1]
l.User = cleanedVal[2]
l.Fd = cleanedVal[3]
l.Type = cleanedVal[4]
l.Device = cleanedVal[5]
l.SizeOff = cleanedVal[6]
l.Node = cleanedVal[7]
l.Name = cleanedVal[8]
if l.Node == &quot;TCP&quot; {
l.TCPState = cleanedVal[9]
count, ok := tcpState[l.TCPState]
if !ok {
tcpState[l.TCPState] = 1
} else {
tcpState[l.TCPState] = count + 1
}
}
//fmt.Printf(&quot;\n%+v&quot;, *l)
//result = append(result, l)
}
fmt.Printf(&quot;Port=%d &quot;, port)
for k, v := range tcpState {
fmt.Printf(&quot;{TCP State=%s,Value=%d},&quot;, k, v)
}
fmt.Println()
}

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

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

Can someone let me know what is going wrong?

  • Go Version - 1.7.3

答案1

得分: 3

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

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

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

将其更新为:

......
func connectionsCount() {
    var wg = &sync.WaitGroup{}
    wg.Add(len(ports))
    for _, v := range ports {
        go count(v, wg)
    }
    wg.Wait()
}
func count(port int, wg *sync.WaitGroup) {
.......

这是播放链接:链接

英文:

Here the issue is not with the Ticker
try

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

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

update it to

    .....
func connectionsCount() {
var wg = &amp;sync.WaitGroup{}
wg.Add(len(ports))
for _, v := range ports {
go count(v, wg)
}
wg.Wait()
}
func count(port int, wg *sync.WaitGroup) {
.......

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:

确定