94 lines
6.9 KiB
Python
94 lines
6.9 KiB
Python
import datetime as dt,os,platform,time
|
|
import psutil
|
|
from discord.ext import commands
|
|
from core.threads import run_blocking
|
|
def h(n):
|
|
n=float(n)
|
|
for u in("b","kib","mib","gib","tib"):
|
|
if abs(n)<1024:return f"{n:.2f} {u}"
|
|
n/=1024
|
|
return f"{n:.2f} pib"
|
|
def kv(d):return "\n".join(f"{k}: {v}" for k,v in d.items())
|
|
def rd(p):
|
|
try:
|
|
with open(p) as f:return f.read().strip()
|
|
except OSError:return ""
|
|
def system():
|
|
u=platform.uname();r={}
|
|
try:r=platform.freedesktop_os_release()
|
|
except Exception:pass
|
|
b=psutil.boot_time()
|
|
return kv({"system":u.system,"kernel":u.release,"version":u.version,"machine":u.machine,"platform":platform.platform(),"distro":r.get("PRETTY_NAME"),"distro id":r.get("ID"),"distro version":r.get("VERSION_ID"),"libc":" ".join(platform.libc_ver()),"python":f"{platform.python_implementation()} {platform.python_version()}","compiler":platform.python_compiler(),"build":" ".join(platform.python_build()),"boot":dt.datetime.fromtimestamp(b).isoformat(),"uptime":str(dt.timedelta(seconds=int(time.time()-b))),"entropy":rd("/proc/sys/kernel/random/entropy_avail"),"max pid":rd("/proc/sys/kernel/pid_max"),"max threads":rd("/proc/sys/kernel/threads-max"),"file max":rd("/proc/sys/fs/file-max"),"file nr":rd("/proc/sys/fs/file-nr"),"swappiness":rd("/proc/sys/vm/swappiness"),"overcommit":rd("/proc/sys/vm/overcommit_memory"),"tainted":rd("/proc/sys/kernel/tainted"),"cpu vulns":len(os.listdir("/sys/devices/system/cpu/vulnerabilities")) if os.path.isdir("/sys/devices/system/cpu/vulnerabilities") else 0})
|
|
def clock():
|
|
n=dt.datetime.now().astimezone()
|
|
return kv({"local":n.isoformat(),"utc":dt.datetime.now(dt.timezone.utc).isoformat(),"tz":n.tzname(),"offset":n.utcoffset(),"time.tzname":time.tzname,"timezone":time.timezone,"altzone":time.altzone,"daylight":time.daylight,"iso week":n.isocalendar()[:2],"day of year":n.timetuple().tm_yday,"epoch":time.time(),"monotonic":time.monotonic(),"perf_counter":time.perf_counter(),"process time":time.process_time(),"clock res":time.get_clock_info("monotonic").resolution})
|
|
def cpu():
|
|
pc=psutil.cpu_percent(interval=1,percpu=True);fr=psutil.cpu_freq(percpu=True) or []
|
|
info={}
|
|
for l in rd("/proc/cpuinfo").splitlines():
|
|
if ":" in l:
|
|
k,v=l.split(":",1);info.setdefault(k.strip(),v.strip())
|
|
cores="\n".join(f" core {i:>2}: {p:5.1f}%"+(f" @ {fr[i].current:.0f} mhz ({fr[i].min:.0f}-{fr[i].max:.0f})" if i<len(fr) else "") for i,p in enumerate(pc))
|
|
return kv({"model":info.get("model name","unknown"),"vendor":info.get("vendor_id"),"family":info.get("cpu family"),"model id":info.get("model"),"stepping":info.get("stepping"),"microcode":info.get("microcode"),"cache":info.get("cache size"),"bogomips":info.get("bogomips"),"physical":psutil.cpu_count(False),"logical":psutil.cpu_count(),"total %":round(sum(pc)/len(pc),1),"loadavg":os.getloadavg(),"times":psutil.cpu_times()._asdict(),"times %":psutil.cpu_times_percent()._asdict(),"stats":psutil.cpu_stats()._asdict(),"flags":info.get("flags"),"per core":"\n"+cores})
|
|
def mem():
|
|
v=psutil.virtual_memory()._asdict();s=psutil.swap_memory()._asdict()
|
|
f=lambda d:{k:(x if k in("percent","sin","sout") else h(x)) for k,x in d.items()}
|
|
mi={}
|
|
for l in rd("/proc/meminfo").splitlines():
|
|
k,_,x=l.partition(":");mi[k]=x.strip()
|
|
ex={k:mi[k] for k in("Dirty","Writeback","Mapped","AnonPages","PageTables","KernelStack","Hugepagesize","HugePages_Total","CommitLimit","Committed_AS","VmallocUsed") if k in mi}
|
|
return "ram\n"+kv(f(v))+"\nswap\n"+kv(f(s))+"\nextra\n"+kv(ex)
|
|
def disks():
|
|
o=[]
|
|
for n,p in enumerate(psutil.disk_partitions()):
|
|
try:u=psutil.disk_usage(p.mountpoint);o.append(f"part{n} {p.fstype} [{p.opts}] {h(u.used)}/{h(u.total)} ({u.percent}%) free {h(u.free)}")
|
|
except Exception:pass
|
|
for k,v in psutil.disk_io_counters(perdisk=True).items():
|
|
o.append(f"io {k}: read {h(v.read_bytes)} ({v.read_count}) write {h(v.write_bytes)} ({v.write_count}) read time {v.read_time}ms write time {v.write_time}ms busy {getattr(v,'busy_time','-')}ms")
|
|
return "\n".join(o)
|
|
def net():
|
|
st=psutil.net_if_stats();io=psutil.net_io_counters(pernic=True);o=[]
|
|
for k,a in psutil.net_if_addrs().items():
|
|
s=st.get(k);i=io.get(k)
|
|
o.append(f"{k}: up={s.isup if s else '?'} speed={s.speed if s else '?'} mb duplex={s.duplex.name if s else '?'} mtu={s.mtu if s else '?'}"+(f" rx={h(i.bytes_recv)} ({i.packets_recv} pkts) tx={h(i.bytes_sent)} ({i.packets_sent} pkts) err={i.errin}/{i.errout} drop={i.dropin}/{i.dropout}" if i else ""))
|
|
o.append(" families: "+", ".join(sorted({x.family.name for x in a})))
|
|
t=io.get
|
|
tot=psutil.net_io_counters()
|
|
o.append(f"total: rx={h(tot.bytes_recv)} tx={h(tot.bytes_sent)} err={tot.errin}/{tot.errout} drop={tot.dropin}/{tot.dropout}")
|
|
try:
|
|
c=psutil.net_connections();z={};k={}
|
|
for x in c:
|
|
z[x.status]=z.get(x.status,0)+1;k[x.type.name]=k.get(x.type.name,0)+1
|
|
o.append(f"connections: {len(c)} {z} {k}")
|
|
except Exception:pass
|
|
return "\n".join(o)
|
|
def sensors():
|
|
o=[]
|
|
for k,v in (getattr(psutil,"sensors_temperatures",lambda:{})() or {}).items():o+=[f"temp {k}/{x.label or '-'}: {x.current} c (high {x.high} crit {x.critical})" for x in v]
|
|
for k,v in (getattr(psutil,"sensors_fans",lambda:{})() or {}).items():o+=[f"fan {k}/{x.label or '-'}: {x.current} rpm" for x in v]
|
|
b=getattr(psutil,"sensors_battery",lambda:None)()
|
|
if b:o.append(f"battery: {b.percent:.0f}% plugged={b.power_plugged} left={b.secsleft}")
|
|
return "\n".join(o) or "no sensors"
|
|
def procs():
|
|
z={};t=0;n=0;top=[]
|
|
for p in psutil.process_iter(["status","num_threads","memory_percent","cpu_percent"]):
|
|
i=p.info;z[i["status"]]=z.get(i["status"],0)+1;t+=i["num_threads"] or 0;n+=1;top.append((i["memory_percent"] or 0,i["cpu_percent"] or 0))
|
|
top.sort(reverse=True)
|
|
return kv({"processes":n,"threads":t,"by status":z,"top mem %":[round(a,2) for a,_ in top[:5]],"mem % sum":round(sum(a for a,_ in top),1)})
|
|
def me():
|
|
p=psutil.Process();m=p.memory_info()
|
|
return kv({"pid":p.pid,"ppid":p.ppid(),"threads":p.num_threads(),"rss":h(m.rss),"vms":h(m.vms),"shared":h(m.shared),"fds":p.num_fds(),"ctx switches":p.num_ctx_switches()._asdict(),"cpu times":p.cpu_times()._asdict(),"io":p.io_counters()._asdict() if hasattr(p,"io_counters") else "-","started":dt.datetime.fromtimestamp(p.create_time()).isoformat(),"nice":p.nice(),"status":p.status()})
|
|
def build():
|
|
o=[]
|
|
for t,f in(("system",system),("time",clock),("cpu",cpu),("memory",mem),("disks",disks),("network",net),("sensors",sensors),("processes",procs),("bot process",me)):
|
|
try:b=f()
|
|
except Exception as e:b=f"n/a: {e!r}"
|
|
o.append(f"===== {t} =====\n{b}")
|
|
return "\n\n".join(o)
|
|
class status(commands.Cog):
|
|
def __init__(s,bot):s.bot=bot
|
|
@commands.command()
|
|
async def status(s,ctx):
|
|
d=await run_blocking(build);await ctx.send(f"```\n{d}\n```")
|
|
async def setup(bot):await bot.add_cog(status(bot))
|