mirror of https://github.com/aristocratos/bpytop
Added: Disks io stat graphs and a dedicated io mode for disks box
parent
4176203cc6
commit
9ad92b180d
293
bpytop.py
293
bpytop.py
|
@ -173,6 +173,16 @@ only_physical=$only_physical
|
||||||
#* Read disks list from /etc/fstab. This also disables only_physical.
|
#* Read disks list from /etc/fstab. This also disables only_physical.
|
||||||
use_fstab=$use_fstab
|
use_fstab=$use_fstab
|
||||||
|
|
||||||
|
#* Toggles io mode for disks, showing only big graphs for disk read/write speeds.
|
||||||
|
io_mode=$io_mode
|
||||||
|
|
||||||
|
#* Set to True to show combined read/write io graphs in io mode.
|
||||||
|
io_graph_combined=$io_graph_combined
|
||||||
|
|
||||||
|
#* Set the top speed for the io graphs in MiB/s (10 by default), use format "device:speed" seperate disks with a comma ",".
|
||||||
|
#* Example: "/dev/sda:100, /dev/sdb:20"
|
||||||
|
io_graph_speeds="$io_graph_speeds"
|
||||||
|
|
||||||
#* Set fixed values for network graphs, default "10M" = 10 Mibibytes, possible units "K", "M", "G", append with "bit" for bits instead of bytes, i.e "100mbit"
|
#* Set fixed values for network graphs, default "10M" = 10 Mibibytes, possible units "K", "M", "G", append with "bit" for bits instead of bytes, i.e "100mbit"
|
||||||
net_download="$net_download"
|
net_download="$net_download"
|
||||||
net_upload="$net_upload"
|
net_upload="$net_upload"
|
||||||
|
@ -372,7 +382,7 @@ class Config:
|
||||||
"proc_colors", "proc_gradient", "proc_per_core", "proc_mem_bytes", "disks_filter", "update_check", "log_level", "mem_graphs", "show_swap",
|
"proc_colors", "proc_gradient", "proc_per_core", "proc_mem_bytes", "disks_filter", "update_check", "log_level", "mem_graphs", "show_swap",
|
||||||
"swap_disk", "show_disks", "use_fstab", "net_download", "net_upload", "net_auto", "net_color_fixed", "show_init", "theme_background",
|
"swap_disk", "show_disks", "use_fstab", "net_download", "net_upload", "net_auto", "net_color_fixed", "show_init", "theme_background",
|
||||||
"net_sync", "show_battery", "tree_depth", "cpu_sensor", "show_coretemp", "proc_update_mult", "shown_boxes", "net_iface", "only_physical",
|
"net_sync", "show_battery", "tree_depth", "cpu_sensor", "show_coretemp", "proc_update_mult", "shown_boxes", "net_iface", "only_physical",
|
||||||
"truecolor"]
|
"truecolor", "io_mode", "io_graph_combined", "io_graph_speeds"]
|
||||||
conf_dict: Dict[str, Union[str, int, bool]] = {}
|
conf_dict: Dict[str, Union[str, int, bool]] = {}
|
||||||
color_theme: str = "Default"
|
color_theme: str = "Default"
|
||||||
theme_background: bool = True
|
theme_background: bool = True
|
||||||
|
@ -402,6 +412,9 @@ class Config:
|
||||||
show_disks: bool = True
|
show_disks: bool = True
|
||||||
only_physical: bool = True
|
only_physical: bool = True
|
||||||
use_fstab: bool = False
|
use_fstab: bool = False
|
||||||
|
io_mode: bool = False
|
||||||
|
io_graph_combined: bool = False
|
||||||
|
io_graph_speeds: str = ""
|
||||||
net_download: str = "10M"
|
net_download: str = "10M"
|
||||||
net_upload: str = "10M"
|
net_upload: str = "10M"
|
||||||
net_color_fixed: bool = False
|
net_color_fixed: bool = False
|
||||||
|
@ -1363,17 +1376,19 @@ class Graph:
|
||||||
max_value: int
|
max_value: int
|
||||||
color_max_value: int
|
color_max_value: int
|
||||||
offset: int
|
offset: int
|
||||||
|
no_zero: bool
|
||||||
current: bool
|
current: bool
|
||||||
last: int
|
last: int
|
||||||
symbol: Dict[float, str]
|
symbol: Dict[float, str]
|
||||||
|
|
||||||
def __init__(self, width: int, height: int, color: Union[List[str], Color, None], data: List[int], invert: bool = False, max_value: int = 0, offset: int = 0, color_max_value: Union[int, None] = None):
|
def __init__(self, width: int, height: int, color: Union[List[str], Color, None], data: List[int], invert: bool = False, max_value: int = 0, offset: int = 0, color_max_value: Union[int, None] = None, no_zero: bool = False):
|
||||||
self.graphs: Dict[bool, List[str]] = {False : [], True : []}
|
self.graphs: Dict[bool, List[str]] = {False : [], True : []}
|
||||||
self.current: bool = True
|
self.current: bool = True
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
self.invert = invert
|
self.invert = invert
|
||||||
self.offset = offset
|
self.offset = offset
|
||||||
|
self.no_zero = no_zero
|
||||||
if not data: data = [0]
|
if not data: data = [0]
|
||||||
if max_value:
|
if max_value:
|
||||||
self.max_value = max_value
|
self.max_value = max_value
|
||||||
|
@ -1436,13 +1451,14 @@ class Graph:
|
||||||
else:
|
else:
|
||||||
if self.height == 1: value[side] = round(val * 4 / 100 + 0.5)
|
if self.height == 1: value[side] = round(val * 4 / 100 + 0.5)
|
||||||
else: value[side] = round((val - h_low) * 4 / (h_high - h_low) + 0.1)
|
else: value[side] = round((val - h_low) * 4 / (h_high - h_low) + 0.1)
|
||||||
|
if self.no_zero and not (new and v == 0 and side == "left") and h == self.height - 1 and value[side] < 1: value[side] = 1
|
||||||
if new: self.last = data[v]
|
if new: self.last = data[v]
|
||||||
self.graphs[self.current][h] += self.symbol[float(value["left"] + value["right"] / 10)]
|
self.graphs[self.current][h] += self.symbol[float(value["left"] + value["right"] / 10)]
|
||||||
if data: self.last = data[-1]
|
if data: self.last = data[-1]
|
||||||
self.out = ""
|
self.out = ""
|
||||||
|
|
||||||
if self.height == 1:
|
if self.height == 1:
|
||||||
self.out += f'{"" if not self.colors else self.colors[self.last]}{self.graphs[self.current][0]}'
|
self.out += f'{"" if not self.colors else (THEME.inactive_fg if self.last < 5 else self.colors[self.last])}{self.graphs[self.current][0]}'
|
||||||
elif self.height > 1:
|
elif self.height > 1:
|
||||||
for h in range(self.height):
|
for h in range(self.height):
|
||||||
if h > 0: self.out += f'{Mv.d(1)}{Mv.l(self.width)}'
|
if h > 0: self.out += f'{Mv.d(1)}{Mv.l(self.width)}'
|
||||||
|
@ -1483,6 +1499,7 @@ class Graphs:
|
||||||
detailed_cpu: Graph = NotImplemented
|
detailed_cpu: Graph = NotImplemented
|
||||||
detailed_mem: Graph = NotImplemented
|
detailed_mem: Graph = NotImplemented
|
||||||
pid_cpu: Dict[int, Graph] = {}
|
pid_cpu: Dict[int, Graph] = {}
|
||||||
|
disk_io: Dict[str, Dict[str, Graph]] = {}
|
||||||
|
|
||||||
class Meter:
|
class Meter:
|
||||||
'''Creates a percentage meter
|
'''Creates a percentage meter
|
||||||
|
@ -1907,6 +1924,9 @@ class MemBox(Box):
|
||||||
divider: int = 0
|
divider: int = 0
|
||||||
mem_width: int = 0
|
mem_width: int = 0
|
||||||
disks_width: int = 0
|
disks_width: int = 0
|
||||||
|
disks_io_h: int = 0
|
||||||
|
disks_io_order: List[str] = []
|
||||||
|
graph_speeds: Dict[str, int] = {}
|
||||||
graph_height: int
|
graph_height: int
|
||||||
resized: bool = True
|
resized: bool = True
|
||||||
redraw: bool = False
|
redraw: bool = False
|
||||||
|
@ -1997,6 +2017,7 @@ class MemBox(Box):
|
||||||
gli: str = ""
|
gli: str = ""
|
||||||
x, y, w, h = cls.x + 1, cls.y + 1, cls.width - 2, cls.height - 2
|
x, y, w, h = cls.x + 1, cls.y + 1, cls.width - 2, cls.height - 2
|
||||||
if cls.resized or cls.redraw:
|
if cls.resized or cls.redraw:
|
||||||
|
cls.redraw = True
|
||||||
cls._calc_size()
|
cls._calc_size()
|
||||||
out_misc += cls._draw_bg()
|
out_misc += cls._draw_bg()
|
||||||
Meters.mem = {}
|
Meters.mem = {}
|
||||||
|
@ -2017,6 +2038,37 @@ class MemBox(Box):
|
||||||
Meters.swap[name] = Graph(cls.mem_meter, cls.graph_height, THEME.gradient[name], mem.swap_vlist[name])
|
Meters.swap[name] = Graph(cls.mem_meter, cls.graph_height, THEME.gradient[name], mem.swap_vlist[name])
|
||||||
else:
|
else:
|
||||||
Meters.swap[name] = Meter(mem.swap_percent[name], cls.mem_meter, name)
|
Meters.swap[name] = Meter(mem.swap_percent[name], cls.mem_meter, name)
|
||||||
|
|
||||||
|
d_graph: List[str] = []
|
||||||
|
d_no_graph: List[str] = []
|
||||||
|
l_vals: List[Tuple[str, int, str, bool]] = []
|
||||||
|
if CONFIG.io_mode:
|
||||||
|
cls.disks_io_h = (cls.height - 2 - len(MemCollector.disks)) // max(1, len(MemCollector.disks_io_dict))
|
||||||
|
if cls.disks_io_h < 2: cls.disks_io_h = 1 if CONFIG.io_graph_combined else 2
|
||||||
|
else:
|
||||||
|
cls.disks_io_h = 1
|
||||||
|
|
||||||
|
if CONFIG.io_graph_speeds and not cls.graph_speeds:
|
||||||
|
try:
|
||||||
|
cls.graph_speeds = { spds.split(":")[0] : int(spds.split(":")[1]) for spds in list(i.strip() for i in CONFIG.io_graph_speeds.split(","))}
|
||||||
|
except (KeyError, ValueError):
|
||||||
|
errlog.error("Wrong formatting in io_graph_speeds variable. Using defaults.")
|
||||||
|
for name in mem.disks.keys():
|
||||||
|
if name in mem.disks_io_dict:
|
||||||
|
d_graph.append(name)
|
||||||
|
else:
|
||||||
|
d_no_graph.append(name)
|
||||||
|
continue
|
||||||
|
if CONFIG.io_graph_combined or not CONFIG.io_mode:
|
||||||
|
l_vals = [("rw", cls.disks_io_h, "available", False)]
|
||||||
|
else:
|
||||||
|
l_vals = [("read", cls.disks_io_h // 2, "free", False), ("write", cls.disks_io_h // 2, "used", True)]
|
||||||
|
|
||||||
|
Graphs.disk_io[name] = {_name : Graph(width=cls.disks_width - (6 if not CONFIG.io_mode else 0), height=_height, color=THEME.gradient[_gradient],
|
||||||
|
data=mem.disks_io_dict[name][_name], invert=_invert, max_value=cls.graph_speeds.get(name, 10), no_zero=True)
|
||||||
|
for _name, _height, _gradient, _invert in l_vals}
|
||||||
|
cls.disks_io_order = d_graph + d_no_graph
|
||||||
|
|
||||||
if cls.disk_meter > 0:
|
if cls.disk_meter > 0:
|
||||||
for n, name in enumerate(mem.disks.keys()):
|
for n, name in enumerate(mem.disks.keys()):
|
||||||
if n * 2 > h: break
|
if n * 2 > h: break
|
||||||
|
@ -2032,6 +2084,10 @@ class MemBox(Box):
|
||||||
Key.mouse["s"] = [[x + w - 6 + i, y-1] for i in range(4)]
|
Key.mouse["s"] = [[x + w - 6 + i, y-1] for i in range(4)]
|
||||||
out_misc += (f'{Mv.to(y-1, x + w - 7)}{THEME.mem_box(Symbol.title_left)}{Fx.b if CONFIG.swap_disk else ""}'
|
out_misc += (f'{Mv.to(y-1, x + w - 7)}{THEME.mem_box(Symbol.title_left)}{Fx.b if CONFIG.swap_disk else ""}'
|
||||||
f'{THEME.hi_fg("s")}{THEME.title("wap")}{Fx.ub}{THEME.mem_box(Symbol.title_right)}')
|
f'{THEME.hi_fg("s")}{THEME.title("wap")}{Fx.ub}{THEME.mem_box(Symbol.title_right)}')
|
||||||
|
if not "i" in Key.mouse:
|
||||||
|
Key.mouse["i"] = [[x + w - 10 + i, y-1] for i in range(2)]
|
||||||
|
out_misc += (f'{Mv.to(y-1, x + w - 11)}{THEME.mem_box(Symbol.title_left)}{Fx.b if CONFIG.io_mode else ""}'
|
||||||
|
f'{THEME.title("i")}{THEME.hi_fg("o")}{Fx.ub}{THEME.mem_box(Symbol.title_right)}')
|
||||||
|
|
||||||
if Collector.collect_interrupt: return
|
if Collector.collect_interrupt: return
|
||||||
Draw.buffer("mem_misc", out_misc, only_save=True)
|
Draw.buffer("mem_misc", out_misc, only_save=True)
|
||||||
|
@ -2080,24 +2136,62 @@ class MemBox(Box):
|
||||||
cx = x + cls.mem_width - 1; cy = 0
|
cx = x + cls.mem_width - 1; cy = 0
|
||||||
big_disk: bool = cls.disks_width >= 25
|
big_disk: bool = cls.disks_width >= 25
|
||||||
gli = f'{Mv.l(2)}{THEME.div_line}{Symbol.title_right}{Symbol.h_line * cls.disks_width}{THEME.mem_box}{Symbol.title_left}{Mv.l(cls.disks_width - 1)}'
|
gli = f'{Mv.l(2)}{THEME.div_line}{Symbol.title_right}{Symbol.h_line * cls.disks_width}{THEME.mem_box}{Symbol.title_left}{Mv.l(cls.disks_width - 1)}'
|
||||||
for name, item in mem.disks.items():
|
if CONFIG.io_mode:
|
||||||
if Collector.collect_interrupt: return
|
for name in cls.disks_io_order:
|
||||||
if not name in Meters.disks_used:
|
item = mem.disks[name]
|
||||||
continue
|
io_item = mem.disks_io_dict.get(name, {})
|
||||||
if cy > h - 2: break
|
if Collector.collect_interrupt: return
|
||||||
out += Fx.trans(f'{Mv.to(y+cy, x+cx)}{gli}{THEME.title}{Fx.b}{item["name"]:{cls.disks_width - 2}.12}{Mv.to(y+cy, x + cx + cls.disks_width - 11)}{item["total"][:None if big_disk else -2]:>9}')
|
|
||||||
out += f'{Mv.to(y+cy, x + cx + (cls.disks_width // 2) - (len(item["io"]) // 2) - 2)}{Fx.ub}{THEME.main_fg}{item["io"]}{Fx.ub}{THEME.main_fg}{Mv.to(y+cy+1, x+cx)}'
|
|
||||||
out += f'Used:{str(item["used_percent"]) + "%":>4} ' if big_disk else "U "
|
|
||||||
out += f'{Meters.disks_used[name](None if cls.resized else mem.disks[name]["used_percent"])}{item["used"][:None if big_disk else -2]:>{9 if big_disk else 7}}'
|
|
||||||
cy += 2
|
|
||||||
|
|
||||||
if len(mem.disks) * 3 <= h + 1:
|
|
||||||
if cy > h - 1: break
|
if cy > h - 1: break
|
||||||
out += Mv.to(y+cy, x+cx)
|
out += Fx.trans(f'{Mv.to(y+cy, x+cx)}{gli}{THEME.title}{Fx.b}{item["name"]:{cls.disks_width - 2}.12}{Mv.to(y+cy, x + cx + cls.disks_width - 11)}{item["total"][:None if big_disk else -2]:>9}')
|
||||||
out += f'Free:{str(item["free_percent"]) + "%":>4} ' if big_disk else f'{"F "}'
|
if big_disk:
|
||||||
out += f'{Meters.disks_free[name](None if cls.resized else mem.disks[name]["free_percent"])}{item["free"][:None if big_disk else -2]:>{9 if big_disk else 7}}'
|
out += Fx.trans(f'{Mv.to(y+cy, x + cx + (cls.disks_width // 2) - (len(str(item["used_percent"])) // 2) - 2)}{Fx.ub}{THEME.main_fg}{item["used_percent"]}%')
|
||||||
cy += 1
|
cy += 1
|
||||||
if len(mem.disks) * 4 <= h + 1: cy += 1
|
|
||||||
|
if io_item:
|
||||||
|
if cy > h - 1: break
|
||||||
|
if CONFIG.io_graph_combined:
|
||||||
|
if cls.disks_io_h <= 1:
|
||||||
|
out += f'{Mv.to(y+cy, x+cx-1)}{" " * 5}'
|
||||||
|
out += (f'{Mv.to(y+cy, x+cx-1)}{Fx.ub}{Graphs.disk_io[name]["rw"](None if cls.redraw else mem.disks_io_dict[name]["rw"][-1])}'
|
||||||
|
f'{Mv.to(y+cy, x+cx-1)}{THEME.main_fg}{item["io"] or "RW"}')
|
||||||
|
cy += cls.disks_io_h
|
||||||
|
else:
|
||||||
|
if cls.disks_io_h <= 3:
|
||||||
|
out += f'{Mv.to(y+cy, x+cx-1)}{" " * 5}{Mv.to(y+cy+1, x+cx-1)}{" " * 5}'
|
||||||
|
out += (f'{Mv.to(y+cy, x+cx-1)}{Fx.ub}{Graphs.disk_io[name]["read"](None if cls.redraw else mem.disks_io_dict[name]["read"][-1])}'
|
||||||
|
f'{Mv.to(y+cy, x+cx-1)}{THEME.main_fg}{item["io_r"] or "R"}')
|
||||||
|
cy += cls.disks_io_h // 2
|
||||||
|
out += f'{Mv.to(y+cy, x+cx-1)}{Graphs.disk_io[name]["write"](None if cls.redraw else mem.disks_io_dict[name]["write"][-1])}'
|
||||||
|
cy += cls.disks_io_h // 2
|
||||||
|
out += f'{Mv.to(y+cy-1, x+cx-1)}{THEME.main_fg}{item["io_w"] or "W"}'
|
||||||
|
else:
|
||||||
|
for name, item in mem.disks.items():
|
||||||
|
if Collector.collect_interrupt: return
|
||||||
|
if not name in Meters.disks_used:
|
||||||
|
continue
|
||||||
|
if cy > h - 1: break
|
||||||
|
out += Fx.trans(f'{Mv.to(y+cy, x+cx)}{gli}{THEME.title}{Fx.b}{item["name"]:{cls.disks_width - 2}.12}{Mv.to(y+cy, x + cx + cls.disks_width - 11)}{item["total"][:None if big_disk else -2]:>9}')
|
||||||
|
if big_disk:
|
||||||
|
out += f'{Mv.to(y+cy, x + cx + (cls.disks_width // 2) - (len(item["io"]) // 2) - 2)}{Fx.ub}{THEME.main_fg}{item["io"]}'
|
||||||
|
cy += 1
|
||||||
|
if cy > h - 1: break
|
||||||
|
if name in Graphs.disk_io:
|
||||||
|
out += f'{Mv.to(y+cy, x+cx-1)}{THEME.main_fg}{Fx.ub}{" IO: " if big_disk else " IO " + Mv.l(2)}{Fx.ub}{Graphs.disk_io[name]["rw"](None if cls.redraw else mem.disks_io_dict[name]["rw"][-1])}'
|
||||||
|
if not big_disk and item["io"]:
|
||||||
|
out += f'{Mv.to(y+cy, x+cx-1)}{Fx.ub}{THEME.main_fg}{item["io"]}'
|
||||||
|
cy += 1
|
||||||
|
if cy > h - 1: break
|
||||||
|
out += Mv.to(y+cy, x+cx) + (f'Used:{str(item["used_percent"]) + "%":>4} ' if big_disk else "U ")
|
||||||
|
out += f'{Meters.disks_used[name](None if cls.resized else mem.disks[name]["used_percent"])}{item["used"][:None if big_disk else -2]:>{9 if big_disk else 7}}'
|
||||||
|
cy += 1
|
||||||
|
|
||||||
|
if len(mem.disks) * 3 + len(mem.disks_io_dict) <= h + 1:
|
||||||
|
if cy > h - 1: break
|
||||||
|
out += Mv.to(y+cy, x+cx)
|
||||||
|
out += f'Free:{str(item["free_percent"]) + "%":>4} ' if big_disk else f'{"F "}'
|
||||||
|
out += f'{Meters.disks_free[name](None if cls.resized else mem.disks[name]["free_percent"])}{item["free"][:None if big_disk else -2]:>{9 if big_disk else 7}}'
|
||||||
|
cy += 1
|
||||||
|
if len(mem.disks) * 4 + len(mem.disks_io_dict) <= h + 1: cy += 1
|
||||||
except (KeyError, TypeError):
|
except (KeyError, TypeError):
|
||||||
return
|
return
|
||||||
Draw.buffer(cls.buffer, f'{out_misc}{out}{Term.fg}', only_save=Menu.active)
|
Draw.buffer(cls.buffer, f'{out_misc}{out}{Term.fg}', only_save=Menu.active)
|
||||||
|
@ -2412,16 +2506,16 @@ class ProcBox(Box):
|
||||||
if cls.selected == 0:
|
if cls.selected == 0:
|
||||||
Key.mouse["enter"] = [[dx+dw-10 + i, dy-1] for i in range(7)]
|
Key.mouse["enter"] = [[dx+dw-10 + i, dy-1] for i in range(7)]
|
||||||
if cls.selected == 0 and not killed:
|
if cls.selected == 0 and not killed:
|
||||||
Key.mouse["t"] = [[dx+2 + i, dy-1] for i in range(9)]
|
Key.mouse["T"] = [[dx+2 + i, dy-1] for i in range(9)]
|
||||||
|
|
||||||
out_misc += (f'{Mv.to(dy-1, dx+dw - 11)}{THEME.proc_box(Symbol.title_left)}{Fx.b}{title if cls.selected > 0 else THEME.title}close{Fx.ub} {main if cls.selected > 0 else THEME.main_fg}{Symbol.enter}{THEME.proc_box(Symbol.title_right)}'
|
out_misc += (f'{Mv.to(dy-1, dx+dw - 11)}{THEME.proc_box(Symbol.title_left)}{Fx.b}{title if cls.selected > 0 else THEME.title}close{Fx.ub} {main if cls.selected > 0 else THEME.main_fg}{Symbol.enter}{THEME.proc_box(Symbol.title_right)}'
|
||||||
f'{Mv.to(dy-1, dx+1)}{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}t{title}erminate{Fx.ub}{THEME.proc_box(Symbol.title_right)}')
|
f'{Mv.to(dy-1, dx+1)}{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}T{title}erminate{Fx.ub}{THEME.proc_box(Symbol.title_right)}')
|
||||||
if dw > 28:
|
if dw > 28:
|
||||||
if cls.selected == 0 and not killed and not "k" in Key.mouse: Key.mouse["k"] = [[dx + 13 + i, dy-1] for i in range(4)]
|
if cls.selected == 0 and not killed and not "K" in Key.mouse: Key.mouse["K"] = [[dx + 13 + i, dy-1] for i in range(4)]
|
||||||
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}k{title}ill{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}K{title}ill{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
||||||
if dw > 39:
|
if dw > 39:
|
||||||
if cls.selected == 0 and not killed and not "i" in Key.mouse: Key.mouse["i"] = [[dx + 19 + i, dy-1] for i in range(9)]
|
if cls.selected == 0 and not killed and not "I" in Key.mouse: Key.mouse["I"] = [[dx + 19 + i, dy-1] for i in range(9)]
|
||||||
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}i{title}nterrupt{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}I{title}nterrupt{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
||||||
|
|
||||||
if Graphs.detailed_cpu is NotImplemented or cls.resized:
|
if Graphs.detailed_cpu is NotImplemented or cls.resized:
|
||||||
Graphs.detailed_cpu = Graph(dgw+1, 7, THEME.gradient["cpu"], proc.details_cpu)
|
Graphs.detailed_cpu = Graph(dgw+1, 7, THEME.gradient["cpu"], proc.details_cpu)
|
||||||
|
@ -2485,14 +2579,14 @@ class ProcBox(Box):
|
||||||
f'{THEME.proc_box(Symbol.title_left)}{title}{Fx.b}info {Fx.ub}{main}{Symbol.enter}{THEME.proc_box(Symbol.title_right)}')
|
f'{THEME.proc_box(Symbol.title_left)}{title}{Fx.b}info {Fx.ub}{main}{Symbol.enter}{THEME.proc_box(Symbol.title_right)}')
|
||||||
if not "enter" in Key.mouse: Key.mouse["enter"] = [[x + 14 + i, y+h] for i in range(6)]
|
if not "enter" in Key.mouse: Key.mouse["enter"] = [[x + 14 + i, y+h] for i in range(6)]
|
||||||
if w - len(loc_string) > 34:
|
if w - len(loc_string) > 34:
|
||||||
if not "t" in Key.mouse: Key.mouse["t"] = [[x + 22 + i, y+h] for i in range(9)]
|
if not "t" in Key.mouse: Key.mouse["T"] = [[x + 22 + i, y+h] for i in range(9)]
|
||||||
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}t{title}erminate{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}T{title}erminate{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
||||||
if w - len(loc_string) > 40:
|
if w - len(loc_string) > 40:
|
||||||
if not "k" in Key.mouse: Key.mouse["k"] = [[x + 33 + i, y+h] for i in range(4)]
|
if not "k" in Key.mouse: Key.mouse["K"] = [[x + 33 + i, y+h] for i in range(4)]
|
||||||
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}k{title}ill{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}K{title}ill{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
||||||
if w - len(loc_string) > 51:
|
if w - len(loc_string) > 51:
|
||||||
if not "i" in Key.mouse: Key.mouse["i"] = [[x + 39 + i, y+h] for i in range(9)]
|
if not "i" in Key.mouse: Key.mouse["I"] = [[x + 39 + i, y+h] for i in range(9)]
|
||||||
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}i{title}nterrupt{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}I{title}nterrupt{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
||||||
if CONFIG.proc_tree and w - len(loc_string) > 65:
|
if CONFIG.proc_tree and w - len(loc_string) > 65:
|
||||||
if not " " in Key.mouse: Key.mouse[" "] = [[x + 50 + i, y+h] for i in range(12)]
|
if not " " in Key.mouse: Key.mouse[" "] = [[x + 50 + i, y+h] for i in range(12)]
|
||||||
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}spc {title}collapse{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
out_misc += f'{THEME.proc_box(Symbol.title_left)}{Fx.b}{hi}spc {title}collapse{Fx.ub}{THEME.proc_box(Symbol.title_right)}'
|
||||||
|
@ -3025,10 +3119,14 @@ class MemCollector(Collector):
|
||||||
disks: Dict[str, Dict]
|
disks: Dict[str, Dict]
|
||||||
disk_hist: Dict[str, Tuple] = {}
|
disk_hist: Dict[str, Tuple] = {}
|
||||||
timestamp: float = time()
|
timestamp: float = time()
|
||||||
|
disks_io_dict: Dict[str, Dict[str, List[int]]] = {}
|
||||||
|
recheck_diskutil: bool = True
|
||||||
|
diskutil_map: Dict[str, str] = {}
|
||||||
|
|
||||||
io_error: bool = False
|
io_error: bool = False
|
||||||
|
|
||||||
old_disks: List[str] = []
|
old_disks: List[str] = []
|
||||||
|
old_io_disks: List[str] = []
|
||||||
|
|
||||||
fstab_filter: List[str] = []
|
fstab_filter: List[str] = []
|
||||||
|
|
||||||
|
@ -3093,9 +3191,9 @@ class MemCollector(Collector):
|
||||||
disk_name: str
|
disk_name: str
|
||||||
filtering: Tuple = ()
|
filtering: Tuple = ()
|
||||||
filter_exclude: bool = False
|
filter_exclude: bool = False
|
||||||
io_string: str
|
io_string_r: str
|
||||||
|
io_string_w: str
|
||||||
u_percent: int
|
u_percent: int
|
||||||
disk_list: List[str] = []
|
|
||||||
cls.disks = {}
|
cls.disks = {}
|
||||||
|
|
||||||
if CONFIG.disks_filter:
|
if CONFIG.disks_filter:
|
||||||
|
@ -3104,9 +3202,8 @@ class MemCollector(Collector):
|
||||||
filtering = tuple(v.strip() for v in CONFIG.disks_filter.replace("exclude=", "").strip().split(","))
|
filtering = tuple(v.strip() for v in CONFIG.disks_filter.replace("exclude=", "").strip().split(","))
|
||||||
else:
|
else:
|
||||||
filtering = tuple(v.strip() for v in CONFIG.disks_filter.strip().split(","))
|
filtering = tuple(v.strip() for v in CONFIG.disks_filter.strip().split(","))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
io_counters = psutil.disk_io_counters(perdisk=SYSTEM == "Linux", nowrap=True)
|
io_counters = psutil.disk_io_counters(perdisk=SYSTEM != "BSD", nowrap=True)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
if not cls.io_error:
|
if not cls.io_error:
|
||||||
cls.io_error = True
|
cls.io_error = True
|
||||||
|
@ -3116,6 +3213,22 @@ class MemCollector(Collector):
|
||||||
errlog.exception(f'{e}')
|
errlog.exception(f'{e}')
|
||||||
io_counters = None
|
io_counters = None
|
||||||
|
|
||||||
|
if SYSTEM == "MacOS" and cls.recheck_diskutil:
|
||||||
|
cls.recheck_diskutil = False
|
||||||
|
try:
|
||||||
|
dutil_out = subprocess.check_output(["diskutil", "list", "physical"], universal_newlines=True)
|
||||||
|
for line in dutil_out.split("\n"):
|
||||||
|
line = line.replace("\u2068", "").replace("\u2069", "")
|
||||||
|
if line.startswith("/dev/"):
|
||||||
|
xdisk = line.split()[0].replace("/dev/", "")
|
||||||
|
elif "Container" in line:
|
||||||
|
ydisk = line.split()[3]
|
||||||
|
if xdisk and ydisk:
|
||||||
|
cls.diskutil_map[xdisk] = ydisk
|
||||||
|
xdisk = ydisk = ""
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
if CONFIG.use_fstab and SYSTEM != "MacOS" and not cls.fstab_filter:
|
if CONFIG.use_fstab and SYSTEM != "MacOS" and not cls.fstab_filter:
|
||||||
try:
|
try:
|
||||||
with open('/etc/fstab','r') as fstab:
|
with open('/etc/fstab','r') as fstab:
|
||||||
|
@ -3128,24 +3241,21 @@ class MemCollector(Collector):
|
||||||
errlog.debug(f'new fstab_filter set : {cls.fstab_filter}')
|
errlog.debug(f'new fstab_filter set : {cls.fstab_filter}')
|
||||||
except IOError:
|
except IOError:
|
||||||
CONFIG.use_fstab = False
|
CONFIG.use_fstab = False
|
||||||
errlog.debug(f'Error reading fstab, use_fstab flag reset to {CONFIG.use_fstab}')
|
errlog.warning(f'Error reading fstab, use_fstab flag reset to {CONFIG.use_fstab}')
|
||||||
if not CONFIG.use_fstab and cls.fstab_filter:
|
if not CONFIG.use_fstab and cls.fstab_filter:
|
||||||
cls.fstab_filter = []
|
cls.fstab_filter = []
|
||||||
errlog.debug(f'use_fstab flag has been turned to {CONFIG.use_fstab}, fstab_filter cleared')
|
errlog.debug(f'use_fstab flag has been turned to {CONFIG.use_fstab}, fstab_filter cleared')
|
||||||
|
|
||||||
for disk in psutil.disk_partitions(all=CONFIG.use_fstab or not CONFIG.only_physical):
|
for disk in psutil.disk_partitions(all=CONFIG.use_fstab or not CONFIG.only_physical):
|
||||||
disk_io = None
|
disk_io = None
|
||||||
io_string = ""
|
io_string_r = io_string_w = ""
|
||||||
if CONFIG.use_fstab and disk.mountpoint not in cls.fstab_filter:
|
if CONFIG.use_fstab and disk.mountpoint not in cls.fstab_filter:
|
||||||
continue
|
continue
|
||||||
disk_name = disk.mountpoint.rsplit('/', 1)[-1] if not disk.mountpoint == "/" else "root"
|
disk_name = disk.mountpoint.rsplit('/', 1)[-1] if not disk.mountpoint == "/" else "root"
|
||||||
#while disk_name in disk_list: disk_name += "_"
|
|
||||||
disk_list += [disk_name]
|
|
||||||
if cls.excludes and disk.fstype in cls.excludes:
|
if cls.excludes and disk.fstype in cls.excludes:
|
||||||
continue
|
continue
|
||||||
if filtering and ((not filter_exclude and not disk.mountpoint in filtering) or (filter_exclude and disk.mountpoint in filtering)):
|
if filtering and ((not filter_exclude and not disk.mountpoint in filtering) or (filter_exclude and disk.mountpoint in filtering)):
|
||||||
continue
|
continue
|
||||||
#elif filtering and disk_name.endswith(filtering)
|
|
||||||
if SYSTEM == "MacOS" and disk.mountpoint == "/private/var/vm":
|
if SYSTEM == "MacOS" and disk.mountpoint == "/private/var/vm":
|
||||||
continue
|
continue
|
||||||
try:
|
try:
|
||||||
|
@ -3161,20 +3271,35 @@ class MemCollector(Collector):
|
||||||
#* Collect disk io
|
#* Collect disk io
|
||||||
if io_counters:
|
if io_counters:
|
||||||
try:
|
try:
|
||||||
if SYSTEM == "Linux":
|
if SYSTEM != "BSD":
|
||||||
dev_name = os.path.realpath(disk.device).rsplit('/', 1)[-1]
|
dev_name = os.path.realpath(disk.device).rsplit('/', 1)[-1]
|
||||||
if dev_name.startswith("md"):
|
if not dev_name in io_counters:
|
||||||
try:
|
for names in io_counters:
|
||||||
dev_name = dev_name[:dev_name.index("p")]
|
if names in dev_name:
|
||||||
except:
|
disk_io = io_counters[names]
|
||||||
pass
|
break
|
||||||
disk_io = io_counters[dev_name]
|
else:
|
||||||
|
if cls.diskutil_map:
|
||||||
|
for names, items in cls.diskutil_map.items():
|
||||||
|
if items in dev_name and names in io_counters:
|
||||||
|
disk_io = io_counters[names]
|
||||||
|
else:
|
||||||
|
disk_io = io_counters[dev_name]
|
||||||
elif disk.mountpoint == "/":
|
elif disk.mountpoint == "/":
|
||||||
disk_io = io_counters
|
disk_io = io_counters
|
||||||
else:
|
else:
|
||||||
raise Exception
|
raise Exception
|
||||||
disk_read = round((disk_io.read_bytes - cls.disk_hist[disk.device][0]) / (time() - cls.timestamp))
|
disk_read = round((disk_io.read_bytes - cls.disk_hist[disk.device][0]) / (time() - cls.timestamp)) #type: ignore
|
||||||
disk_write = round((disk_io.write_bytes - cls.disk_hist[disk.device][1]) / (time() - cls.timestamp))
|
disk_write = round((disk_io.write_bytes - cls.disk_hist[disk.device][1]) / (time() - cls.timestamp)) #type: ignore
|
||||||
|
if not disk.device in cls.disks_io_dict:
|
||||||
|
cls.disks_io_dict[disk.device] = {"read" : [], "write" : [], "rw" : []}
|
||||||
|
cls.disks_io_dict[disk.device]["read"].append(disk_read >> 20)
|
||||||
|
cls.disks_io_dict[disk.device]["write"].append(disk_write >> 20)
|
||||||
|
cls.disks_io_dict[disk.device]["rw"].append((disk_read + disk_write) >> 20)
|
||||||
|
|
||||||
|
if len(cls.disks_io_dict[disk.device]["read"]) > MemBox.width:
|
||||||
|
del cls.disks_io_dict[disk.device]["read"][0], cls.disks_io_dict[disk.device]["write"][0], cls.disks_io_dict[disk.device]["rw"][0]
|
||||||
|
|
||||||
except:
|
except:
|
||||||
disk_read = disk_write = 0
|
disk_read = disk_write = 0
|
||||||
else:
|
else:
|
||||||
|
@ -3182,15 +3307,18 @@ class MemCollector(Collector):
|
||||||
|
|
||||||
if disk_io:
|
if disk_io:
|
||||||
cls.disk_hist[disk.device] = (disk_io.read_bytes, disk_io.write_bytes)
|
cls.disk_hist[disk.device] = (disk_io.read_bytes, disk_io.write_bytes)
|
||||||
if MemBox.disks_width > 30:
|
if CONFIG.io_mode or MemBox.disks_width > 30:
|
||||||
if disk_read > 0:
|
if disk_read > 0:
|
||||||
io_string += f'▲{floating_humanizer(disk_read, short=True)} '
|
io_string_r = f'▲{floating_humanizer(disk_read, short=True)}'
|
||||||
if disk_write > 0:
|
if disk_write > 0:
|
||||||
io_string += f'▼{floating_humanizer(disk_write, short=True)}'
|
io_string_w = f'▼{floating_humanizer(disk_write, short=True)}'
|
||||||
|
if CONFIG.io_mode:
|
||||||
|
cls.disks[disk.device]["io_r"] = io_string_r
|
||||||
|
cls.disks[disk.device]["io_w"] = io_string_w
|
||||||
elif disk_read + disk_write > 0:
|
elif disk_read + disk_write > 0:
|
||||||
io_string += f'▼▲{floating_humanizer(disk_read + disk_write, short=True)}'
|
io_string_r += f'▼▲{floating_humanizer(disk_read + disk_write, short=True)}'
|
||||||
|
|
||||||
cls.disks[disk.device]["io"] = io_string
|
cls.disks[disk.device]["io"] = io_string_r + (" " if io_string_w and io_string_r else "") + io_string_w
|
||||||
|
|
||||||
if CONFIG.swap_disk and MemBox.swap_on:
|
if CONFIG.swap_disk and MemBox.swap_on:
|
||||||
cls.disks["__swap"] = { "name" : "swap", "used_percent" : cls.swap_percent["used"], "free_percent" : cls.swap_percent["free"], "io" : "" }
|
cls.disks["__swap"] = { "name" : "swap", "used_percent" : cls.swap_percent["used"], "free_percent" : cls.swap_percent["free"], "io" : "" }
|
||||||
|
@ -3205,9 +3333,11 @@ class MemCollector(Collector):
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if disk_list != cls.old_disks:
|
if cls.old_disks != list(cls.disks) or cls.old_io_disks != list(cls.disks_io_dict):
|
||||||
MemBox.redraw = True
|
MemBox.redraw = True
|
||||||
cls.old_disks = disk_list.copy()
|
cls.recheck_diskutil = True
|
||||||
|
cls.old_disks = list(cls.disks)
|
||||||
|
cls.old_io_disks = list(cls.disks_io_dict)
|
||||||
|
|
||||||
cls.timestamp = time()
|
cls.timestamp = time()
|
||||||
|
|
||||||
|
@ -3852,6 +3982,8 @@ class Menu:
|
||||||
"(Home) (End)" : "Jump to first or last page in process list.",
|
"(Home) (End)" : "Jump to first or last page in process list.",
|
||||||
"(Left) (Right)" : "Select previous/next sorting column.",
|
"(Left) (Right)" : "Select previous/next sorting column.",
|
||||||
"(b) (n)" : "Select previous/next network device.",
|
"(b) (n)" : "Select previous/next network device.",
|
||||||
|
"(s)" : "Toggle showing swap as a disk.",
|
||||||
|
"(i)" : "Toggle disks io mode with big graphs.",
|
||||||
"(z)" : "Toggle totals reset for current network device",
|
"(z)" : "Toggle totals reset for current network device",
|
||||||
"(a)" : "Toggle auto scaling for the network graphs.",
|
"(a)" : "Toggle auto scaling for the network graphs.",
|
||||||
"(y)" : "Toggle synced scaling mode for network graphs.",
|
"(y)" : "Toggle synced scaling mode for network graphs.",
|
||||||
|
@ -3860,9 +3992,9 @@ class Menu:
|
||||||
"(r)" : "Reverse sorting order in processes box.",
|
"(r)" : "Reverse sorting order in processes box.",
|
||||||
"(e)" : "Toggle processes tree view.",
|
"(e)" : "Toggle processes tree view.",
|
||||||
"(delete)" : "Clear any entered filter.",
|
"(delete)" : "Clear any entered filter.",
|
||||||
"Selected (T, t)" : "Terminate selected process with SIGTERM - 15.",
|
"Selected (T)" : "Terminate selected process with SIGTERM - 15.",
|
||||||
"Selected (K, k)" : "Kill selected process with SIGKILL - 9.",
|
"Selected (K)" : "Kill selected process with SIGKILL - 9.",
|
||||||
"Selected (I, i)" : "Interrupt selected process with SIGINT - 2.",
|
"Selected (I)" : "Interrupt selected process with SIGINT - 2.",
|
||||||
"_1" : " ",
|
"_1" : " ",
|
||||||
"_2" : "For bug reporting and project updates, visit:",
|
"_2" : "For bug reporting and project updates, visit:",
|
||||||
"_3" : "https://github.com/aristocratos/bpytop",
|
"_3" : "https://github.com/aristocratos/bpytop",
|
||||||
|
@ -4094,6 +4226,30 @@ class Menu:
|
||||||
'Split memory box to also show disks.',
|
'Split memory box to also show disks.',
|
||||||
'',
|
'',
|
||||||
'True or False.'],
|
'True or False.'],
|
||||||
|
"io_mode" : [
|
||||||
|
'Toggles io mode for disks.',
|
||||||
|
'',
|
||||||
|
'Shows big graphs for disk read/write speeds',
|
||||||
|
'instead of used/free percentage meters.',
|
||||||
|
'',
|
||||||
|
'True or False.'],
|
||||||
|
"io_graph_combined" : [
|
||||||
|
'Toggle combined read and write graphs.',
|
||||||
|
'',
|
||||||
|
'Only has effect if "io mode" is True.',
|
||||||
|
'',
|
||||||
|
'True or False.'],
|
||||||
|
"io_graph_speeds" : [
|
||||||
|
'Set top speeds for the io graphs.',
|
||||||
|
'',
|
||||||
|
'Manually set which speed in MiB/s that equals',
|
||||||
|
'100 percent in the io graphs.',
|
||||||
|
'(10 MiB/s by default).',
|
||||||
|
'',
|
||||||
|
'Format: "device:speed" seperate disks with a',
|
||||||
|
'comma ",".',
|
||||||
|
'',
|
||||||
|
'Example: "/dev/sda:100, /dev/sdb:20".'],
|
||||||
"show_swap" : [
|
"show_swap" : [
|
||||||
'If swap memory should be shown in memory box.',
|
'If swap memory should be shown in memory box.',
|
||||||
'',
|
'',
|
||||||
|
@ -4244,6 +4400,7 @@ class Menu:
|
||||||
loglevel_i: int = CONFIG.log_levels.index(CONFIG.log_level)
|
loglevel_i: int = CONFIG.log_levels.index(CONFIG.log_level)
|
||||||
cpu_sensor_i: int = CONFIG.cpu_sensors.index(CONFIG.cpu_sensor)
|
cpu_sensor_i: int = CONFIG.cpu_sensors.index(CONFIG.cpu_sensor)
|
||||||
color_i: int
|
color_i: int
|
||||||
|
max_opt_len: int = max([len(categories[x]) for x in categories]) * 2
|
||||||
cat_list = list(categories)
|
cat_list = list(categories)
|
||||||
while not cls.close:
|
while not cls.close:
|
||||||
key = ""
|
key = ""
|
||||||
|
@ -4252,7 +4409,7 @@ class Menu:
|
||||||
selected_cat = list(categories)[cat_int]
|
selected_cat = list(categories)[cat_int]
|
||||||
option_items = categories[cat_list[cat_int]]
|
option_items = categories[cat_list[cat_int]]
|
||||||
option_len: int = len(option_items) * 2
|
option_len: int = len(option_items) * 2
|
||||||
y = 12 if Term.height < option_len + 13 else Term.height // 2 - option_len // 2 + 7
|
y = 12 if Term.height < max_opt_len + 13 else Term.height // 2 - max_opt_len // 2 + 7
|
||||||
out_misc = (f'{Banner.draw(y-10, center=True)}{Mv.d(1)}{Mv.l(46)}{Colors.black_bg}{Colors.default}{Fx.b}← esc'
|
out_misc = (f'{Banner.draw(y-10, center=True)}{Mv.d(1)}{Mv.l(46)}{Colors.black_bg}{Colors.default}{Fx.b}← esc'
|
||||||
f'{Mv.r(30)}{Fx.i}Version: {VERSION}{Fx.ui}{Fx.ub}{Term.bg}{Term.fg}')
|
f'{Mv.r(30)}{Fx.i}Version: {VERSION}{Fx.ui}{Fx.ub}{Term.bg}{Term.fg}')
|
||||||
x = Term.width//2-38
|
x = Term.width//2-38
|
||||||
|
@ -4409,6 +4566,8 @@ class Menu:
|
||||||
elif selected == "draw_clock":
|
elif selected == "draw_clock":
|
||||||
Box.clock_on = len(CONFIG.draw_clock) > 0
|
Box.clock_on = len(CONFIG.draw_clock) > 0
|
||||||
if not Box.clock_on: Draw.clear("clock", saved=True)
|
if not Box.clock_on: Draw.clear("clock", saved=True)
|
||||||
|
elif selected == "io_graph_speeds":
|
||||||
|
MemBox.graph_speeds = {}
|
||||||
Term.refresh(force=True)
|
Term.refresh(force=True)
|
||||||
cls.resized = False
|
cls.resized = False
|
||||||
elif key == "backspace" and len(input_val):
|
elif key == "backspace" and len(input_val):
|
||||||
|
@ -4441,7 +4600,7 @@ class Menu:
|
||||||
cat_int = int(key) - 1
|
cat_int = int(key) - 1
|
||||||
change_cat = True
|
change_cat = True
|
||||||
elif key == "enter" and selected in ["update_ms", "disks_filter", "custom_cpu_name", "net_download",
|
elif key == "enter" and selected in ["update_ms", "disks_filter", "custom_cpu_name", "net_download",
|
||||||
"net_upload", "draw_clock", "tree_depth", "proc_update_mult", "shown_boxes", "net_iface"]:
|
"net_upload", "draw_clock", "tree_depth", "proc_update_mult", "shown_boxes", "net_iface", "io_graph_speeds"]:
|
||||||
inputting = True
|
inputting = True
|
||||||
input_val = str(getattr(CONFIG, selected))
|
input_val = str(getattr(CONFIG, selected))
|
||||||
elif key == "left" and selected == "update_ms" and CONFIG.update_ms - 100 >= 100:
|
elif key == "left" and selected == "update_ms" and CONFIG.update_ms - 100 >= 100:
|
||||||
|
@ -5023,12 +5182,12 @@ def process_keys():
|
||||||
ProcBox.filtering = True
|
ProcBox.filtering = True
|
||||||
if not ProcCollector.search_filter: ProcBox.start = 0
|
if not ProcCollector.search_filter: ProcBox.start = 0
|
||||||
Collector.collect(ProcCollector, redraw=True, only_draw=True)
|
Collector.collect(ProcCollector, redraw=True, only_draw=True)
|
||||||
elif key.lower() in ["t", "k", "i"] and (ProcBox.selected > 0 or ProcCollector.detailed):
|
elif key in ["T", "K", "I"] and (ProcBox.selected > 0 or ProcCollector.detailed):
|
||||||
pid: int = ProcBox.selected_pid if ProcBox.selected > 0 else ProcCollector.detailed_pid # type: ignore
|
pid: int = ProcBox.selected_pid if ProcBox.selected > 0 else ProcCollector.detailed_pid # type: ignore
|
||||||
if psutil.pid_exists(pid):
|
if psutil.pid_exists(pid):
|
||||||
if key.lower() == "t": sig = signal.SIGTERM
|
if key == "T": sig = signal.SIGTERM
|
||||||
elif key.lower() == "k": sig = signal.SIGKILL
|
elif key == "K": sig = signal.SIGKILL
|
||||||
elif key.lower() == "i": sig = signal.SIGINT
|
elif key == "I": sig = signal.SIGINT
|
||||||
try:
|
try:
|
||||||
os.kill(pid, sig)
|
os.kill(pid, sig)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -5089,6 +5248,10 @@ def process_keys():
|
||||||
Collector.collect_idle.wait()
|
Collector.collect_idle.wait()
|
||||||
CONFIG.show_disks = not CONFIG.show_disks
|
CONFIG.show_disks = not CONFIG.show_disks
|
||||||
Collector.collect(MemCollector, interrupt=True, redraw=True)
|
Collector.collect(MemCollector, interrupt=True, redraw=True)
|
||||||
|
elif key == "i":
|
||||||
|
Collector.collect_idle.wait()
|
||||||
|
CONFIG.io_mode = not CONFIG.io_mode
|
||||||
|
Collector.collect(MemCollector, interrupt=True, redraw=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue