nohang/os07
2019-01-30 03:05:08 +09:00

221 lines
4.9 KiB
Python
Executable File

#!/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 = kib_to_mib(int(f_list[i].split('\t')[1][:-3]))
if i is vm_swap_index:
vm_swap = kib_to_mib(int(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():
pass
def kib_to_mib(num):
"""Convert KiB values to MiB values."""
return round(num / 1024.0)
def human(num):
'''Convert KiB to MiB and right align, as you see'''
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 = 20
if display_cmdline is None:
display_cmdline = 20
"""#######################################################################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((
pid, oom_score, oom_score_adj, cmdline, name, uid, vm_rss, vm_swap))
# list sorted by oom_score
oom_list_sorted = sorted(oom_list, key=itemgetter(1), reverse=True)
"""#######################################################################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),
uid.rjust(5),
str(pid).rjust(max_pid_len),
name.ljust(15),
human(vm_rss),
human(vm_swap),
cmdline[:int(display_cmdline)]
)
)