in agent/channel/channel_gshell.go [108:179]
func (c *GshellChannel) startChannelUnsafe() error {
if !c.Working.CompareAndSwap(false, true) {
log.GetLogger().Warning("startChannelUnsafe run duplicated, return it")
return nil // startChannelUnsage 同一时间只能有一个执行
}
var gshellPath string
var e error
var h *os.File
gshellPath, e = getGshellPath()
if e == nil {
h, e = os.OpenFile(gshellPath, os.O_RDWR, 0666)
}
if e != nil {
metrics.GetChannelFailEvent(
metrics.EVENT_SUBCATEGORY_CHANNEL_GSHELL,
"errormsg", fmt.Sprintf("open gshell failed: %s error: %s", gshellPath, e),
"filepath", gshellPath,
"type", ChannelTypeStr(c.ChannelType),
).ReportEvent()
log.GetLogger().Errorln("open gshell failed:", gshellPath, "error:", e)
c.Working.Clear()
return e
}
log.GetLogger().Infoln("open gshell ok:", gshellPath)
c.hGshell = h
c.WaitCheckDone.Add(1)
go func() {
defer c.Working.Clear()
defer c.hGshell.Close()
defer c.WaitCheckDone.Done()
tick := time.NewTicker(time.Duration(200) * time.Millisecond)
defer tick.Stop()
buf := make([]byte, 2048)
var lastKickvmFreqExceedTime time.Time
for {
<-tick.C
n, err := c.hGshell.Read(buf)
if err == nil && n > 0 {
reachedFrequencyLimit, count, period := c.hasReachFrequencyLimit()
retStr := c.CallBack(string(buf[:n]), ChannelGshellType)
if len(retStr) > 0 {
log.GetLogger().Infoln("write:", retStr)
_, err = c.hGshell.Write([]byte(retStr + "\n"))
if err != nil {
log.GetLogger().Errorln("write error:", err)
report := clientreport.ClientReport{
ReportType: "switch_channel_in_gshell",
Info: fmt.Sprintf("start switch :" + err.Error()),
}
clientreport.SendReport(report)
go c.SwitchChannel()
return
}
}
if reachedFrequencyLimit && (time.Since(lastKickvmFreqExceedTime) > intervalToOpenNoGshellChannel) {
lastKickvmFreqExceedTime = time.Now()
tip := fmt.Sprintf("gshell kick_vm has reached max frequency %d times during %d seconds, "+
"try to open no-gshell channel", count, period)
log.GetLogger().Info(tip)
report := clientreport.ClientReport{
ReportType: "switch_channel_in_gshell",
Info: fmt.Sprintf("start switch :" + tip),
}
clientreport.SendReport(report)
// just try to open no-gshell cahnnel, do not close gshell self
go c.openOtherChannel()
}
}
}
}()
return nil
}