func()

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
}