写在前面
最近在修改调试系统中的日志展示,日志展示用的是websocket,用curl不好测试,所以动手写了一个客户端来查看系统日志。
websocket client
代码如下(代码中有bug,不要复制粘贴)
package main
import (
"fmt"
"log"
"os"
"os/signal"
"syscall"
"golang.org/x/net/websocket"
)
func main() {
url := os.Args[1]
origin := os.Args[2]
fmt.Printf("Dial url: %s ,origin: %s\n", url, origin)
ws, err := websocket.Dial(url, "", origin)
if err != nil {
log.Fatal(err)
}
var msg = make([]byte, 512)
go func() {
for {
ws.Read(msg)
m, err := ws.Read(msg)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", msg[:m])
}
}()
errs := make(chan error, 2)
go func() {
c := make(chan os.Signal)
signal.Notify(c, syscall.SIGINT)
errs <- fmt.Errorf("%s", <-c)
}()
fmt.Printf("terminated: %v", <-errs)
ws.Close() //关闭连接
}
然后编译执行,发现只打印了偶数行?
./wscat ws://127.0.0.1:8888/watch/clusterlog?clusterid=cb63a0bc-8273-45ef-a966-67b46968e518 http://127.0.0.1:8888
Dial url: ws://127.0.0.1:8888/watch/clusterlog?clusterid=cb63a0bc-8273-45ef-a966-67b46968e518 ,origin: http://127.0.0.1:8888
Receive: b
Receive: d
Receive: f
Receive: h
没多想,由于server端代码不太熟,先入为主的以为是server端的问题(因为client端代码太少了,太盲目自大了),所以拆分核心处理模块,把server精简成一个小程序来测试,这里贴上server端代码:
package main
import (
"fmt"
"net/http"
"strings"
"time"
"github.com/hpcloud/tail"
"golang.org/x/net/websocket"
)
func echoHandler(ws *websocket.Conn) {
cid := ws.Request().URL.Query().Get("clusterid")
// get agent ansible output log.
filename := "/var/log/" + cid + ".idx"
t, err := tail.TailFile(filename, tail.Config{
ReOpen: true,
Follow: true,
// Location: &tail.SeekInfo{Offset: 0, Whence: 2},
MustExist: false,
Poll: true,
})
if err != nil {
fmt.Println("tail file err:", err)
return
}
var line *tail.Line
var ok bool
lastwoline := false
for {
line, ok = <-t.Lines
if !ok {
time.Sleep(100 * time.Millisecond)
continue
}
_, err := ws.Write([]byte(line.Text))
if err != nil {
fmt.Printf("Error: %s", err)
return
}
if lastwoline {
break
}
if strings.Contains(line.Text, "PLAY RECAP") {
lastwoline = true
}
}
}
func main() {
http.Handle("/watch/clusterlog", websocket.Handler(echoHandler))
err := http.ListenAndServe(":8080", nil)
if err != nil {
panic("ListenAndServe: " + err.Error())
}
}
还是没什么卵用,还是只打印log的奇数行,看代码不仔细,下面祭出golang的单步代码调试神器:delve,详情见下节golang单步调试神器delve。
错误原因是wscat的32行,ws.Read读了两遍
以上↑