package autotask import ( c "ciyon/zciyon" "fmt" "net/http" "os" "path/filepath" "regexp" "strings" "time" ) func funcindex() map[string]func(map[string]any) string { return map[string]func(map[string]any) string{ "web\\admin\\autotask\\base::dayclean": dayclean, "web\\admin\\autotask\\base::srvstats": srvstats, } } func srvstats(systemrow map[string]any) string { defer func() { if r := recover(); r != nil { fmt.Println("srvstats panic:", r) c.Log.Error("AUTO", "srvstats panic:"+r.(string)) } }() func_succ := c.CiyVars.Func_succ func_fail := c.CiyVars.Func_fail func_commit := c.CiyVars.Func_commit func_rollback := c.CiyVars.Func_rollback func_runms := 0 if func_succ+func_fail > 0 { func_runms = c.CiyVars.Func_runms / (func_commit + func_rollback + 1) } c.CiyVars.Func_succ = 0 c.CiyVars.Func_fail = 0 c.CiyVars.Func_commit = 0 c.CiyVars.Func_rollback = 0 c.CiyVars.Func_runms = 0 disk := c.Ciy_sys_getdisk("/") disk2 := c.Ciy_sys_getdisk("/data") disk_sysfree := disk["free"] disk_datafree := disk2["free"] starttime := c.Timems() fpath := c.CiyWebDir + "/ud/_" + c.Tostr(c.Tostamp()) + ".bin" fsize := 1024 * 1024 // 1MB fcontent := make([]byte, fsize) for i := 0; i < fsize; i++ { fcontent[i] = byte(i%70 + 30) } f, err := os.Create(fpath) if err != nil { c.Log.Error("FILE", "创建临时文件失败"+fpath+":"+err.Error()) } else { f.Write(fcontent) f.Close() rcontent, err := os.ReadFile(fpath) if err != nil { c.Log.Error("FILE", "读取临时文件失败") } else { for i := 0; i < fsize; i++ { if fcontent[i] != rcontent[i] { c.Log.Error("FILE", "写入临时文件校验失败") break } } os.Remove(fpath) } } disk_ioms := c.Timems() - starttime output := c.RunCmd("ps", "aux", "-A") cmddb := []string{"mysql", "mysqld"} cmdweb := []string{"nginx", "php", "WorkerMan", "mosquitto", "gitea", "/zgo"} cpu := map[string]float64{"db": 0, "web": 0, "oth": 0} mem := map[string]float64{"db": 0, "web": 0, "oth": 0} for _, line := range output { if strings.Contains(line, "COMMAND") { continue } _nextspace(&line) _nextspace(&line) cpup := c.Tofloat(_nextspace(&line)) memp := c.Tofloat(_nextspace(&line)) _nextspace(&line) // 虚拟内存 _nextspace(&line) // 物理内存 包括共享内存 _nextspace(&line) _nextspace(&line) _nextspace(&line) _nextspace(&line) if _arrin(line, cmddb) { cpu["db"] += cpup mem["db"] += memp } else if _arrin(line, cmdweb) { cpu["web"] += cpup mem["web"] += memp } else { cpu["oth"] += cpup mem["oth"] += memp } } output = c.RunCmd("free", "-m") mem_free := 0 matches := regexp.MustCompile(`Mem:\s+(\d+)`).FindStringSubmatch(output[1]) if len(matches) > 1 { mem_free = c.Toint(c.Tofloat(matches[1]) * (100 - cpu["db"] - cpu["web"] - cpu["oth"]) * 1024 * 1024 / 100) } output = c.RunCmd("sh", "-c", "netstat -an | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'") net_tcp := 0 for _, line := range output { ls := strings.Split(line, " ") if ls[0] == "LISTEN" { continue } if len(ls) < 2 { continue } net_tcp += c.Toint(ls[1]) } starttime = c.Timems() resp, err := http.Get("https://www.baidu.com") if err == nil { resp.Body.Close() } net_ioms := c.Timems() - starttime dbrows, err := c.CiyDB.Getraw("show global status") if err != nil { c.Log.Error("FILE", "执行show global status失败") } dbstat := map[string]float64{} for _, row := range dbrows { name := c.Tostr(row["Variable_name"]) val := c.Tofloat(row["Value"]) dbstat[name] = val } db_keyhit := dbstat["Handler_read_key"] / (dbstat["Com_select"] + 1) * 100 db_dbhit := dbstat["Innodb_buffer_pool_reads"] / (dbstat["Innodb_buffer_pool_read_requests"] + 1) * 100 db_tmptable := dbstat["Created_tmp_disk_tables"] / (dbstat["Created_tmp_tables"] + 1) * 100 updata := map[string]any{} updata["func_succ"] = func_succ updata["func_fail"] = func_fail updata["func_commit"] = func_commit updata["func_rollback"] = func_rollback updata["func_runms"] = func_runms updata["disk_sysfree"] = disk_sysfree updata["disk_datafree"] = disk_datafree updata["disk_ioms"] = disk_ioms updata["cpu_free"] = 100 - cpu["db"] - cpu["web"] - cpu["oth"] updata["cpu_db"] = cpu["db"] updata["cpu_web"] = cpu["web"] updata["cpu_oth"] = cpu["oth"] updata["mem_free"] = mem_free updata["mem_db"] = mem["db"] updata["mem_web"] = mem["web"] updata["mem_oth"] = mem["oth"] updata["net_tcp"] = net_tcp updata["net_ioms"] = net_ioms updata["db_query"] = dbstat["Questions"] updata["db_commit"] = dbstat["Com_commit"] updata["db_rollback"] = dbstat["Com_rollback"] updata["db_keyhit"] = db_keyhit updata["db_dbhit"] = db_dbhit updata["db_tmptable"] = db_tmptable updata["db_lock"] = dbstat["Innodb_row_lock_current_waits"] updata["addtimes"] = c.Tostamp() csql := c.NewCiySQL("zc_stats") c.CiyDB.Insert(csql, updata) retmsg := "succ: " + c.Tostr(func_succ) if func_rollback > 0 { retmsg += ", rollback: " + c.Tostr(func_rollback) } return retmsg } func dayclean(systemrow map[string]any) string { maxAge := 3 * 24 * time.Hour cnt := 0 errcnt := 0 filepath.Walk(c.CiyWebDir+"/ud/tmp", func(path string, info os.FileInfo, err error) error { if err != nil { _tasklog(systemrow, "出现错误:"+err.Error()) return err } if info.IsDir() { return nil } if time.Since(info.ModTime()) > maxAge { err := os.Remove(path) cnt++ if err != nil { errcnt++ fmt.Printf("failed to delete file: %s\n", err) } } return nil }) retmsg := "clean: " + c.Tostr(cnt) if errcnt > 0 { retmsg += ", err: " + c.Tostr(errcnt) } return retmsg } func _nextspace(line *string) string { ind := strings.Index(*line, " ") if ind == -1 { *line = "" return *line } va := (*line)[:ind] *line = (*line)[ind:] *line = strings.TrimSpace(*line) return va } func _arrin(cmd string, arr []string) bool { for _, v := range arr { if strings.Contains(cmd, v) { return true } } return false }