diff --git a/base/cli/procstat.go b/base/cli/procstat.go index ffd340f1..4846c542 100644 --- a/base/cli/procstat.go +++ b/base/cli/procstat.go @@ -1,6 +1,7 @@ package cli import ( + "os" "strings" "time" @@ -13,43 +14,51 @@ import ( ) type procstat struct { - user int - sys int - idle int - io int - - total int - free int - available int - - rx int - tx int + utime int64 + stime int64 + vmsize int64 + vmrss int64 + user int64 + sys int64 + idle int64 + total int64 + free int64 + rx int64 + tx int64 + established int64 + time_wait int64 } func newprocstat(m *ice.Message) (stat procstat) { + m.Option(ice.MSG_USERROLE, aaa.ROOT) + if ls := kit.Split(m.Cmdx(nfs.CAT, kit.Format("/proc/%d/stat", os.Getpid())), " ()"); len(ls) > 0 { + stat = procstat{utime: kit.Int64(ls[13]), stime: kit.Int64(ls[14]), vmsize: kit.Int64(ls[22]), vmrss: kit.Int64(ls[23]) * 4096} + } if ls := kit.Split(kit.Select("", strings.Split(m.Cmdx(nfs.CAT, "/proc/stat"), lex.NL), 1)); len(ls) > 0 { - stat = procstat{ - user: kit.Int(ls[1]), - sys: kit.Int(ls[3]), - idle: kit.Int(ls[4]), - io: kit.Int(ls[5]), - } + stat.user = kit.Int64(ls[1]) + stat.sys = kit.Int64(ls[3]) + stat.idle = kit.Int64(ls[4]) } for _, line := range strings.Split(strings.TrimSpace(m.Cmdx(nfs.CAT, "/proc/meminfo")), lex.NL) { switch ls := kit.Split(line, ": "); ls[0] { case "MemTotal": - stat.total = kit.Int(ls[1]) * 1024 + stat.total = kit.Int64(ls[1]) * 1024 case "MemFree": - stat.free = kit.Int(ls[1]) * 1024 - case "MemAvailable": - stat.available = kit.Int(ls[1]) * 1024 + stat.free = kit.Int64(ls[1]) * 1024 } } for _, line := range strings.Split(strings.TrimSpace(m.Cmdx(nfs.CAT, "/proc/net/dev")), lex.NL)[2:] { - ls := kit.Split(line, ": ") - if ls[0] == "eth0" { - stat.rx = kit.Int(ls[1]) - stat.tx = kit.Int(ls[9]) + if ls := kit.Split(line, ": "); ls[0] != "lo" { + stat.rx += kit.Int64(ls[1]) + stat.tx += kit.Int64(ls[9]) + } + } + for _, line := range strings.Split(strings.TrimSpace(m.Cmdx(nfs.CAT, "/proc/net/tcp")), lex.NL)[1:] { + switch ls := kit.Split(line, ": "); ls[5] { + case "01": + stat.established++ + case "06": + stat.time_wait++ } } return @@ -58,29 +67,23 @@ func newprocstat(m *ice.Message) (stat procstat) { func init() { var last procstat Index.MergeCommands(ice.Commands{ - "procstat": {Name: "procstat id auto page insert", Actions: ice.MergeActions(ice.Actions{ - ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - aaa.White(m, "/proc/net/dev") - aaa.White(m, "/proc/meminfo") - aaa.White(m, "/proc/stat") - last = newprocstat(m) - }}, + "procstat": {Name: "procstat id list page", Actions: ice.MergeActions(ice.Actions{ + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { last = newprocstat(m) }}, mdb.INSERT: {Name: "insert", Hand: func(m *ice.Message, arg ...string) { stat := newprocstat(m) - total := stat.user - last.user + stat.sys - last.sys + stat.idle - last.idle + stat.io - last.io + total := stat.user - last.user + stat.sys - last.sys + stat.idle - last.idle m.Cmd(mdb.INSERT, m.PrefixKey(), "", mdb.LIST, - "user", (stat.user-last.user)*1000/total, "sys", (stat.sys-last.sys)*1000/total, - "idle", (stat.idle-last.idle)*1000/total, "io", (stat.io-stat.io)*1000/total, - "free", stat.free*1000/stat.total, "available", stat.available*1000/stat.total, - "rx", (stat.rx-last.rx)*1000/10000000, "tx", (stat.tx-last.tx)*1000/10000000, + "utime", (stat.utime-last.utime+stat.stime-last.stime)*1000/total, "vmrss", stat.vmrss*1000/stat.total, + "user", (stat.user-last.user+stat.sys-last.sys)*1000/total, "idle", (stat.idle-last.idle)*1000/total, "free", stat.free*1000/stat.total, + "rx", (stat.rx-last.rx)*1000/20000000, "tx", (stat.tx-last.tx)*1000/20000000, "established", stat.established, "time_wait", stat.time_wait, ) last = stat }}, - }, mdb.PageListAction(mdb.FIELD, "time,id,user,sys,idle,io,free,available,rx,tx")), Hand: func(m *ice.Message, arg ...string) { - m.OptionDefault(mdb.CACHE_LIMIT, "1000") + }, mdb.PageListAction(mdb.FIELD, "time,id,utime,vmrss,user,idle,free,rx,tx,established,time_wait")), Hand: func(m *ice.Message, arg ...string) { + m.OptionDefault(mdb.CACHE_LIMIT, "300") mdb.PageListSelect(m, arg...) - m.SortInt(mdb.ID).Display("/plugin/story/trend.js", ice.VIEW, "折线图", "min", "0", "max", "1000", mdb.FIELD, "user,sys,idle,free,available,tx,rx", COLOR, "red,yellow,green,blue,cyan,purple") - m.Status("from", m.Append(mdb.TIME), "span", kit.FmtDuration(time.Duration(kit.Time(m.Time())-kit.Time(m.Append(mdb.TIME)))), m.AppendSimple("time,user,sys,idle,free,available,tx,rx"), "cursor", "0") + m.SortInt(mdb.ID).Display("/plugin/story/trend.js", ice.VIEW, "折线图", "min", "0", "max", "1000", COLOR, "yellow,cyan,red,green,blue,purple,purple") + m.Status("from", m.Append(mdb.TIME), "span", kit.FmtDuration(time.Duration(kit.Time(m.Time())-kit.Time(m.Append(mdb.TIME)))), m.AppendSimple(mdb.Config(m, mdb.FIELD)), "cursor", "0") }}, }) } diff --git a/base/tcp/port.go b/base/tcp/port.go index 22b4b872..9e9e3e57 100644 --- a/base/tcp/port.go +++ b/base/tcp/port.go @@ -3,6 +3,7 @@ package tcp import ( "net" "path" + "strconv" "strings" ice "shylinux.com/x/icebergs" @@ -41,13 +42,49 @@ const PORT = "port" func init() { Index.MergeCommands(ice.Commands{ - PORT: {Name: "port port path auto", Help: "端口", Actions: ice.MergeActions(ice.Actions{ + PORT: {Name: "port port path auto socket", Help: "端口", Actions: ice.MergeActions(ice.Actions{ CURRENT: {Hand: func(m *ice.Message, arg ...string) { m.Echo(mdb.Config(m, CURRENT)) }}, aaa.RIGHT: {Hand: func(m *ice.Message, arg ...string) { m.Echo(_port_right(m, arg...)) }}, nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { m.Assert(m.Option(PORT) != "") nfs.Trash(m, path.Join(ice.USR_LOCAL_DAEMON, m.Option(PORT))) }}, + "socket": {Hand: func(m *ice.Message, arg ...string) { + parse := func(str string) int64 { + port, _ := strconv.ParseInt(str, 16, 32) + return port + } + trans := func(str string) string { + switch str { + case "0A": + return "LISTEN" + case "01": + return "ESTABLISHED" + case "06": + return "TIME_WAIT" + default: + return str + } + } + stats := map[string]int{} + m.Spawn().Split(m.Cmdx(nfs.CAT, "/proc/net/tcp")).Table(func(value ice.Maps) { + stats[trans(value["st"])]++ + m.Push("status", trans(value["st"])) + ls := kit.Split(value["local_address"], ":") + m.Push("local", kit.Format("%d.%d.%d.%d:%d", parse(ls[0][6:8]), parse(ls[0][4:6]), parse(ls[0][2:4]), parse(ls[0][:2]), parse(ls[1]))) + ls = kit.Split(value["rem_address"], ":") + m.Push("remote", kit.Format("%d.%d.%d.%d:%d", parse(ls[0][6:8]), parse(ls[0][4:6]), parse(ls[0][2:4]), parse(ls[0][:2]), parse(ls[1]))) + }) + m.Spawn().Split(m.Cmdx(nfs.CAT, "/proc/net/tcp6")).Table(func(value ice.Maps) { + stats[trans(value["st"])]++ + m.Push("status", trans(value["st"])) + ls := kit.Split(value["local_address"], ":") + m.Push("local", kit.Format("%d.%d.%d.%d:%d", parse(ls[0][30:32]), parse(ls[0][28:30]), parse(ls[0][26:28]), parse(ls[0][24:26]), parse(ls[1]))) + ls = kit.Split(value["remote_address"], ":") + m.Push("remote", kit.Format("%d.%d.%d.%d:%d", parse(ls[0][30:32]), parse(ls[0][28:30]), parse(ls[0][26:28]), parse(ls[0][24:26]), parse(ls[1]))) + }) + m.Sort("status,local").StatusTimeCount(stats) + }}, }, mdb.HashAction(BEGIN, 10000, CURRENT, 10000, END, 20000)), Hand: func(m *ice.Message, arg ...string) { if len(arg) > 0 { m.Cmdy(nfs.DIR, arg[1:], kit.Dict(nfs.DIR_ROOT, path.Join(ice.USR_LOCAL_DAEMON, arg[0]))) diff --git a/base/web/serve.go b/base/web/serve.go index 110bb2c1..6c1c620e 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -53,6 +53,7 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { } else { r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, nfs.DF)[0]) } + // kit.For(r.Header, func(k string, v []string) { m.Debug("what %v %v", k, v) }) kit.If(path.Join(r.URL.Path) == nfs.PS, func() { r.URL.Path = kit.Select(nfs.PS, mdb.Config(m, "main")) }) if m.Logs(r.Header.Get(ice.MSG_USERIP), r.Method, r.URL.String()); r.Method == http.MethodGet { if msg := m.Spawn(w, r).Options(ice.MSG_USERUA, r.UserAgent()); path.Join(r.URL.Path) == nfs.PS {