From 4d78e8a41266391f78f5ab585ce16ac3e54eca65 Mon Sep 17 00:00:00 2001 From: Deepak Narayanan Date: Mon, 29 Oct 2018 14:57:21 +0530 Subject: [PATCH 1/4] Add files via upload --- ptop/interfaces/GUI.py | 75 +++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 20 deletions(-) diff --git a/ptop/interfaces/GUI.py b/ptop/interfaces/GUI.py index 83a7f5f..b4b355f 100644 --- a/ptop/interfaces/GUI.py +++ b/ptop/interfaces/GUI.py @@ -6,7 +6,7 @@ import psutil, logging, weakref from ptop.utils import ThreadJob from ptop.constants import SYSTEM_USERS, SUPPORTED_THEMES - +import os # global flags defining actions, would like them to be object vars TIME_SORT = False @@ -184,19 +184,29 @@ def _show_detailed_process_info(self,*args,**kwargs): self.process_details_view_helper.display() self.process_details_view_helper.edit() - def _kill_process(self): + #ISSUE 1 VINU + def _kill_process(self,*args,**kwargs): # Get the PID of the selected process - pid_to_kill = self._get_selected_process_pid() - self._logger.info("Terminating process with pid {0}".format(pid_to_kill)) - target = psutil.Process(int(pid_to_kill)) try: - target.terminate() - self._logger.info("Terminated process with pid {0}".format(pid_to_kill)) + pid_to_kill = self._get_selected_process_pid() + self._logger.info("Terminating process with pid {0}".format(pid_to_kill)) + target = psutil.Process(int(pid_to_kill)) + try: + target.terminate() + self._logger.info("Terminated process with pid {0}".format(pid_to_kill)) + except: + self._logger.info("Not able to terminate process with pid: {0}".format(pid_to_kill), + exc_info=True) except: - self._logger.info("Not able to terminate process with pid: {0}".format(pid_to_kill), - exc_info=True) - + self._logger.info("No process selected") + #ISSUE 2 VINU def _quit(self,*args,**kwargs): + my_pid = os.getpid() + target = psutil.Process(int(my_pid)) + try: + target.terminate() + except: + self._logger.info("Operation failed", exc_info=True) raise KeyboardInterrupt def filter_processes(self): @@ -321,8 +331,9 @@ def draw_chart(self,canvas,y,chart_type): chart_array[self.CHART_WIDTH-1] = y chart_array[self.CHART_WIDTH-2] = y - for x in xrange(0,self.CHART_WIDTH): - for y in xrange(self.CHART_HEIGHT,self.CHART_HEIGHT-chart_array[x],-1): + #ISSUE 0 VINU + for x in range(0,self.CHART_WIDTH): + for y in range(self.CHART_HEIGHT,self.CHART_HEIGHT-chart_array[x],-1): canvas.set(x,y) return canvas.frame(0,0,self.CHART_WIDTH,self.CHART_HEIGHT) @@ -372,31 +383,55 @@ def update(self): processes_info = self.statistics['Process']['text'] system_info = self.statistics['System']['text'] cpu_info = self.statistics['CPU']['graph'] - + + #ISSUE 0 VINU + ttotal = system_info['running_time'].total_seconds() + hhours = int((ttotal/60)//60) + mmins = int((ttotal-60*60*hhours)//60) + ssecs = int(ttotal - hhours*60*60 - mmins*60) + mmins = str(mmins) + hhours = str(hhours) + ssecs = str(ssecs) + hhours = '0'*(2-len(hhours)) + hhours + mmins = '0'*(2-len(mmins)) + mmins + ssecs = '0'*(2-len(ssecs)) + ssecs + timeStr = hhours + ':' + mmins + ':' + ssecs + #### Overview information #### - - row1 = "Disk Usage (/) {4}{0: <6}/{1: >6} MB{4}{2: >2} %{5}Processes{4}{3: <8}".format(disk_info["used"], + row1 = "Disk Usage (/) {4}{0: <7}/{1: >7} MB{4}{2: >2} %{5}Processes{4}{3: <8}".format(disk_info["used"], disk_info["total"], disk_info["percentage"], processes_info["running_processes"], " "*int(4*self.X_SCALING_FACTOR), " "*int(9*self.X_SCALING_FACTOR)) - row2 = "Swap Memory {4}{0: <6}/{1: >6} MB{4}{2: >2} %{5}Threads {4}{3: <8}".format(swap_info["active"], + row2 = "Swap Memory {4}{0: <7}/{1: >7} MB{4}{2: >2} %{5}Threads {4}{3: <8}".format(swap_info["active"], swap_info["total"], swap_info["percentage"], processes_info["running_threads"], " "*int(4*self.X_SCALING_FACTOR), " "*int(9*self.X_SCALING_FACTOR)) - - row3 = "Main Memory {4}{0: <6}/{1: >6} MB{4}{2: >2} %{5}Boot Time{4}{3: <8}".format(memory_info["active"], + #ISSUE 0 VINU + row3 = "Main Memory {4}{0: <7}/{1: >7} MB{4}{2: >2} %{5}Boot Time{4}{3: <8}".format(memory_info["active"], memory_info["total"], memory_info["percentage"], - system_info['running_time'], + timeStr, + " "*int(4*self.X_SCALING_FACTOR), + " "*int(9*self.X_SCALING_FACTOR)) + #ISSUE 3 SMEET + net = psutil.net_io_counters() + sentt = net[0]*0.000001 + sentt = str(round(sentt,2)) + recc = net[1]*0.000001 + recc = str(round(recc,2)) + row4 = "Network Usage:\nSent/Received {4}{0: <7}/{1: >7} MB{4}{2: >2} {5} {4}{3: <8}".format(sentt, + recc, + '', + '', " "*int(4*self.X_SCALING_FACTOR), " "*int(9*self.X_SCALING_FACTOR)) - self.basic_stats.value = row1 + '\n' + row2 + '\n' + row3 + self.basic_stats.value = row1 + '\n' + row2 + '\n' + row3 + '\n' + row4 # Lazy update to GUI self.basic_stats.update(clear=True) From f0df5f4cf8ec9416720671f661e4ea1196c597b7 Mon Sep 17 00:00:00 2001 From: Deepak Narayanan Date: Mon, 29 Oct 2018 15:03:32 +0530 Subject: [PATCH 2/4] Add files via upload Resolved Issues - 18,26,34,33,35 --- ptop/interfaces/GUI.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/ptop/interfaces/GUI.py b/ptop/interfaces/GUI.py index b4b355f..6ddd422 100644 --- a/ptop/interfaces/GUI.py +++ b/ptop/interfaces/GUI.py @@ -184,7 +184,7 @@ def _show_detailed_process_info(self,*args,**kwargs): self.process_details_view_helper.display() self.process_details_view_helper.edit() - #ISSUE 1 VINU + #Issue 33 Killing a process making ptop exit abruptly def _kill_process(self,*args,**kwargs): # Get the PID of the selected process try: @@ -199,7 +199,9 @@ def _kill_process(self,*args,**kwargs): exc_info=True) except: self._logger.info("No process selected") - #ISSUE 2 VINU + + # Issue 26 Kill ptop properly + def _quit(self,*args,**kwargs): my_pid = os.getpid() target = psutil.Process(int(my_pid)) @@ -331,7 +333,7 @@ def draw_chart(self,canvas,y,chart_type): chart_array[self.CHART_WIDTH-1] = y chart_array[self.CHART_WIDTH-2] = y - #ISSUE 0 VINU + # Issue 34 - Python 3 compatibility issue for x in range(0,self.CHART_WIDTH): for y in range(self.CHART_HEIGHT,self.CHART_HEIGHT-chart_array[x],-1): canvas.set(x,y) @@ -384,7 +386,7 @@ def update(self): system_info = self.statistics['System']['text'] cpu_info = self.statistics['CPU']['graph'] - #ISSUE 0 VINU + # Issue 34 Python 3 Compatability Issue ttotal = system_info['running_time'].total_seconds() hhours = int((ttotal/60)//60) mmins = int((ttotal-60*60*hhours)//60) @@ -411,14 +413,14 @@ def update(self): processes_info["running_threads"], " "*int(4*self.X_SCALING_FACTOR), " "*int(9*self.X_SCALING_FACTOR)) - #ISSUE 0 VINU + #Issue 34 Python 3 Compatability Issue row3 = "Main Memory {4}{0: <7}/{1: >7} MB{4}{2: >2} %{5}Boot Time{4}{3: <8}".format(memory_info["active"], memory_info["total"], memory_info["percentage"], timeStr, " "*int(4*self.X_SCALING_FACTOR), " "*int(9*self.X_SCALING_FACTOR)) - #ISSUE 3 SMEET + # Issue 18 Add network stats net = psutil.net_io_counters() sentt = net[0]*0.000001 sentt = str(round(sentt,2)) @@ -653,4 +655,4 @@ def main(self): # time(ms) to wait for user interactions self.keypress_timeout_default = 10 - self.draw() \ No newline at end of file + self.draw() From 96822e8c8ecb2fcce1b0edf975266985af4d16e4 Mon Sep 17 00:00:00 2001 From: Deepak Narayanan Date: Mon, 12 Nov 2018 14:21:41 +0530 Subject: [PATCH 3/4] Add files via upload --- ptop/interfaces/GUI.py | 55 ++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/ptop/interfaces/GUI.py b/ptop/interfaces/GUI.py index 6ddd422..c38ef99 100644 --- a/ptop/interfaces/GUI.py +++ b/ptop/interfaces/GUI.py @@ -15,19 +15,22 @@ PREVIOUS_TERMINAL_WIDTH = None PREVIOUS_TERMINAL_HEIGHT = None -class ProcessDetailsInfoBox(npyscreen.Popup): +class ProcessDetailsInfoBox(npyscreen.PopupWide): + ''' This widget is used to who the detailed information about the selected process in the processes table. Curretly only the port information is shown for a selected process. - - Set them to fix the position - SHOW_ATX = 10 - SHOW_ATY = 2 - ''' - def __init__(self,local_ports,process_pid): +` ''' + #Set them to fix the position + SHOW_ATX = 0 + SHOW_ATY = 0 + DEFAULT_COLUMNS = PREVIOUS_TERMINAL_WIDTH + + def __init__(self,local_ports,process_pid,open_files): self._local_ports = local_ports self._process_pid = process_pid + self._open_files = open_files super(ProcessDetailsInfoBox,self).__init__() def create(self,**kwargs): @@ -36,17 +39,27 @@ def create(self,**kwargs): they are created in the create() method ''' super(ProcessDetailsInfoBox,self).create() + self._logger = logging.getLogger(__name__) - self._logger.info("Showing the local ports {0} used by the process with pid {1}".format(self._local_ports, - str(self._process_pid)) - ) - if len(self._local_ports) != 0: - self.details_box_heading = self.add(npyscreen.TitleText, name='Ports used by the process {0}'.format(str(self._process_pid)),) + self._logger.info("Showing the local ports {0} and files opened and are being used by the process with pid {1}".format(self._local_ports, + str(self._process_pid))) + #logger.info("Showing the local ports {0} and files opened and are being used by the process with pid {1}".format(self._local_ports,str(self._process_pid))) + # self.details_box_heading = self.add(npyscreen.TitleText, name='No ports used by the process {0}'.format(str(self._process_pid)),) + + if len(self._local_ports) != 0 and len(self._open_files)!=0: + self.details_box_heading = self.add(npyscreen.TitleText, name='The Ports used by PID {0} are below.'.format(str(self._process_pid))) self.details_box = self.add(npyscreen.BufferPager) self.details_box.values.extend(self._local_ports) + self.details_box.values.extend('\n') + self.details_box.values.extend(['Files opened by this process are ..\n']) + self.details_box.values.extend('\n') + self.details_box.values.extend(self._open_files) + self.details_box.display() + elif len(self._local_ports) == 0 and len(self._open_files)!=0: + self.details_box_heading = self.add(npyscreen.TitleText, name='Files opened by PID {0} are below. This process is not using any ports.'.format(str(self._process_pid))) + self.details_box = self.add(npyscreen.BufferPager) + self.details_box.values.extend(self._open_files) self.details_box.display() - else: - self.details_box_heading = self.add(npyscreen.TitleText, name='No ports used by the process {0}'.format(str(self._process_pid)),) def adjust_widgets(self): pass @@ -134,6 +147,16 @@ def _get_local_ports_used_by_a_process(self,process_pid): for proc in self._uncurtailed_process_data: if proc['id'] == process_pid: return proc['local_ports'] + + def _list_of_open_files(self,process_pid): + """ + Given the Process ID, return the list of all the open files + """ + files = [] + p = psutil.Process(process_pid) + for i in p.open_files(): + files.append(i[0]) + return files def _sort_by_time(self,*args,**kwargs): # fuck .. that's why NPSManaged was required, i.e you can access the app instance within widgets @@ -179,7 +202,8 @@ def _show_detailed_process_info(self,*args,**kwargs): # self.process_details_view_helper = ProcessDetailsInfoBox(local_ports=['1','2','3']) process_pid = self._get_selected_process_pid() local_ports = self._get_local_ports_used_by_a_process(process_pid) - self.process_details_view_helper = ProcessDetailsInfoBox(local_ports,process_pid) + open_files = self._list_of_open_files(process_pid) + self.process_details_view_helper = ProcessDetailsInfoBox(local_ports,process_pid,open_files) self.process_details_view_helper.owner_widget = weakref.proxy(self) self.process_details_view_helper.display() self.process_details_view_helper.edit() @@ -656,3 +680,4 @@ def main(self): # time(ms) to wait for user interactions self.keypress_timeout_default = 10 self.draw() + From a57982b940d3b619a82c1c1e943b90d193e3b464 Mon Sep 17 00:00:00 2001 From: Deepak Narayanan Date: Mon, 12 Nov 2018 14:29:52 +0530 Subject: [PATCH 4/4] Added Open Files display- Part of Feature Storming --- ptop/interfaces/GUI.py | 80 +++++++++++------------------------------- 1 file changed, 21 insertions(+), 59 deletions(-) diff --git a/ptop/interfaces/GUI.py b/ptop/interfaces/GUI.py index c38ef99..90233cd 100644 --- a/ptop/interfaces/GUI.py +++ b/ptop/interfaces/GUI.py @@ -6,7 +6,7 @@ import psutil, logging, weakref from ptop.utils import ThreadJob from ptop.constants import SYSTEM_USERS, SUPPORTED_THEMES -import os + # global flags defining actions, would like them to be object vars TIME_SORT = False @@ -65,6 +65,7 @@ def adjust_widgets(self): pass + class ProcessFilterInputBox(npyscreen.Popup): ''' Helper widget(input-box) that is used for filtering the processes list @@ -208,31 +209,19 @@ def _show_detailed_process_info(self,*args,**kwargs): self.process_details_view_helper.display() self.process_details_view_helper.edit() - #Issue 33 Killing a process making ptop exit abruptly - def _kill_process(self,*args,**kwargs): + def _kill_process(self): # Get the PID of the selected process + pid_to_kill = self._get_selected_process_pid() + self._logger.info("Terminating process with pid {0}".format(pid_to_kill)) + target = psutil.Process(int(pid_to_kill)) try: - pid_to_kill = self._get_selected_process_pid() - self._logger.info("Terminating process with pid {0}".format(pid_to_kill)) - target = psutil.Process(int(pid_to_kill)) - try: - target.terminate() - self._logger.info("Terminated process with pid {0}".format(pid_to_kill)) - except: - self._logger.info("Not able to terminate process with pid: {0}".format(pid_to_kill), - exc_info=True) + target.terminate() + self._logger.info("Terminated process with pid {0}".format(pid_to_kill)) except: - self._logger.info("No process selected") - - # Issue 26 Kill ptop properly + self._logger.info("Not able to terminate process with pid: {0}".format(pid_to_kill), + exc_info=True) def _quit(self,*args,**kwargs): - my_pid = os.getpid() - target = psutil.Process(int(my_pid)) - try: - target.terminate() - except: - self._logger.info("Operation failed", exc_info=True) raise KeyboardInterrupt def filter_processes(self): @@ -357,9 +346,8 @@ def draw_chart(self,canvas,y,chart_type): chart_array[self.CHART_WIDTH-1] = y chart_array[self.CHART_WIDTH-2] = y - # Issue 34 - Python 3 compatibility issue - for x in range(0,self.CHART_WIDTH): - for y in range(self.CHART_HEIGHT,self.CHART_HEIGHT-chart_array[x],-1): + for x in xrange(0,self.CHART_WIDTH): + for y in xrange(self.CHART_HEIGHT,self.CHART_HEIGHT-chart_array[x],-1): canvas.set(x,y) return canvas.frame(0,0,self.CHART_WIDTH,self.CHART_HEIGHT) @@ -409,55 +397,31 @@ def update(self): processes_info = self.statistics['Process']['text'] system_info = self.statistics['System']['text'] cpu_info = self.statistics['CPU']['graph'] - - # Issue 34 Python 3 Compatability Issue - ttotal = system_info['running_time'].total_seconds() - hhours = int((ttotal/60)//60) - mmins = int((ttotal-60*60*hhours)//60) - ssecs = int(ttotal - hhours*60*60 - mmins*60) - mmins = str(mmins) - hhours = str(hhours) - ssecs = str(ssecs) - hhours = '0'*(2-len(hhours)) + hhours - mmins = '0'*(2-len(mmins)) + mmins - ssecs = '0'*(2-len(ssecs)) + ssecs - timeStr = hhours + ':' + mmins + ':' + ssecs - + #### Overview information #### - row1 = "Disk Usage (/) {4}{0: <7}/{1: >7} MB{4}{2: >2} %{5}Processes{4}{3: <8}".format(disk_info["used"], + + row1 = "Disk Usage (/) {4}{0: <6}/{1: >6} MB{4}{2: >2} %{5}Processes{4}{3: <8}".format(disk_info["used"], disk_info["total"], disk_info["percentage"], processes_info["running_processes"], " "*int(4*self.X_SCALING_FACTOR), " "*int(9*self.X_SCALING_FACTOR)) - row2 = "Swap Memory {4}{0: <7}/{1: >7} MB{4}{2: >2} %{5}Threads {4}{3: <8}".format(swap_info["active"], + row2 = "Swap Memory {4}{0: <6}/{1: >6} MB{4}{2: >2} %{5}Threads {4}{3: <8}".format(swap_info["active"], swap_info["total"], swap_info["percentage"], processes_info["running_threads"], " "*int(4*self.X_SCALING_FACTOR), " "*int(9*self.X_SCALING_FACTOR)) - #Issue 34 Python 3 Compatability Issue - row3 = "Main Memory {4}{0: <7}/{1: >7} MB{4}{2: >2} %{5}Boot Time{4}{3: <8}".format(memory_info["active"], + + row3 = "Main Memory {4}{0: <6}/{1: >6} MB{4}{2: >2} %{5}Boot Time{4}{3: <8}".format(memory_info["active"], memory_info["total"], memory_info["percentage"], - timeStr, - " "*int(4*self.X_SCALING_FACTOR), - " "*int(9*self.X_SCALING_FACTOR)) - # Issue 18 Add network stats - net = psutil.net_io_counters() - sentt = net[0]*0.000001 - sentt = str(round(sentt,2)) - recc = net[1]*0.000001 - recc = str(round(recc,2)) - row4 = "Network Usage:\nSent/Received {4}{0: <7}/{1: >7} MB{4}{2: >2} {5} {4}{3: <8}".format(sentt, - recc, - '', - '', + system_info['running_time'], " "*int(4*self.X_SCALING_FACTOR), " "*int(9*self.X_SCALING_FACTOR)) - self.basic_stats.value = row1 + '\n' + row2 + '\n' + row3 + '\n' + row4 + self.basic_stats.value = row1 + '\n' + row2 + '\n' + row3 # Lazy update to GUI self.basic_stats.update(clear=True) @@ -657,7 +621,6 @@ def draw(self): scaling factors now the dimensions of the CPU_WIDGETS/MEMORY _WIDGETS are used for calculation of the dimensions of the charts. There is padding of width 1 between the boundaries of the widgets and the charts - # self.CHART_WIDTH = int(self.CHART_WIDTH*self.X_SCALING_FACTOR) # self.CHART_HEIGHT = int(self.CHART_HEIGHT*self.Y_SCALING_FACTOR) ''' @@ -679,5 +642,4 @@ def main(self): # time(ms) to wait for user interactions self.keypress_timeout_default = 10 - self.draw() - + self.draw() \ No newline at end of file