英文:
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:<port>
to check number of open TCP connections at a port. Code looks like below:-
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()
}
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("Tick at", 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 = &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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论