#!/usr/bin/env python3 """ sort processes by oom_score """ from operator import itemgetter from os import listdir from argparse import ArgumentParser """#######################################################################79""" # define funtcions def pid_to_oom_score(pid): with open('/proc/' + pid + '/oom_score') as f: return f.readline()[:-1] def pid_to_oom_score_adj(pid): with open('/proc/' + pid + '/oom_score_adj') as f: return f.readline()[:-1] def pid_to_cmdline(pid): """ Get process cmdline by pid. pid: str pid of required process returns string cmdline """ with open('/proc/' + pid + '/cmdline') as f: return f.read().replace('\x00', ' ').rstrip() def pid_to_status_units(pid): with open('/proc/' + pid + '/status', 'rb') as f: f_list = f.read().decode('utf-8', 'ignore').split('\n') for i in range(len(f_list)): if i is 1: name = f_list[0].split('\t')[1] if i is uid_index: uid = f_list[i].split('\t')[2] if i is vm_rss_index: vm_rss = f_list[i].split('\t')[1][:-3] if i is vm_swap_index: vm_swap = f_list[i].split('\t')[1][:-3] return name, uid, vm_rss, vm_swap def get_max_pid_len(): with open('/proc/sys/kernel/pid_max') as file: for line in file: return len(line.strip()) ''' def get_max_vm_rss_len(): with open('/proc/meminfo') as file: kib = file.readline()[:-4].split(':')[1].lstrip() return len(str(round(float(kib) / 1024))) ''' def human(num): '''Convert KiB to MiB and right align''' return str(round(num / 1024.0)).rjust(6, ' ') """#######################################################################79""" # parse input # todo: input validation parser = ArgumentParser() parser.add_argument( '--num', '-n', help="""max number of lines; default: 99999""", default=None, type=str ) parser.add_argument( '--len', '-l', help="""max cmdline length; default: 99999""", default=None, type=str ) args = parser.parse_args() display_cmdline = args.len num_lines = args.num if num_lines is None: num_lines = 99999 if display_cmdline is None: display_cmdline = 99999 """#######################################################################79""" # find VmRSS, VmSwap and UID positions in /proc/*/status with open('/proc/self/status') as file: status_list = file.readlines() # список имен из /proc/*/status для дальнейшего поиска позиций VmRSS and VmSwap status_names = [] for s in status_list: status_names.append(s.split(':')[0]) vm_rss_index = status_names.index('VmRSS') vm_swap_index = status_names.index('VmSwap') uid_index = status_names.index('Uid') """#######################################################################79""" # get sorted list with pid, oom_score, oom_score_adj, cmdline # get status units: name, uid, rss, swap oom_list = [] for pid in listdir('/proc'): # пропускаем элементы, состоящие не из цифр и PID 1 if pid.isdigit() is False or pid == '1': continue try: oom_score = pid_to_oom_score(pid) oom_score_adj = pid_to_oom_score_adj(pid) cmdline = pid_to_cmdline(pid) if cmdline == '': continue name, uid, vm_rss, vm_swap = pid_to_status_units(pid) except FileNotFoundError: continue except ProcessLookupError: continue oom_list.append(( int(pid), int(oom_score), int(oom_score_adj), cmdline, name, int(uid), int(vm_rss), int(vm_swap))) # list sorted by oom_score oom_list_sorted = sorted(oom_list, key=itemgetter(1), reverse=True) ''' max_uid_len = len(str(sorted( oom_list, key=itemgetter(5), reverse=True)[0][5])) max_vm_rss_len = len(str(round( sorted(oom_list, key=itemgetter(6), reverse=True)[0][6] / 1024.0))) ''' """#######################################################################79""" # print table max_pid_len = get_max_pid_len() if display_cmdline == '0': print( 'oom_score oom_score_adj UID{}PID Name ' 'VmRSS VmSwap'.format(' ' * (max_pid_len - 2))) print('--------- ------------- ----- {} --------------- -' '------- --------'.format('-' * max_pid_len)) else: print('oom_score oom_score_adj UID{}PID Name ' ' VmRSS VmSwap cmdline'.format(' ' * (max_pid_len - 2))) print('--------- ------------- ----- {} --------------- -' '------- -------- -------'.format('-' * max_pid_len)) for i in oom_list_sorted[:int(num_lines)]: pid = i[0] oom_score = i[1] oom_score_adj = i[2] cmdline = i[3] name = i[4] uid = i[5] vm_rss = i[6] vm_swap = i[7] print( '{} {} {} {} {} {} M {} M {}'.format( str(oom_score).rjust(9), str(oom_score_adj).rjust(13), str(uid).rjust(5), str(pid).rjust(max_pid_len), name.ljust(15), human(vm_rss), human(vm_swap), cmdline[:int(display_cmdline)] ) )