fix oom-sort: fix UnucideDecodeError and fix PID len

This commit is contained in:
Alexey Avramov 2019-01-30 03:05:08 +09:00
parent fb9f5237ce
commit 15f8a12a02
10 changed files with 1841 additions and 198 deletions

View File

@ -87,8 +87,13 @@ To uninstall:
$ sudo make uninstall
```
For Arch Linux, there's an [AUR package](https://aur.archlinux.org/packages/nohang-git/). Use your favorite [AUR helper](https://wiki.archlinux.org/index.php/AUR_helpers).
For Arch Linux, there's an [AUR package](https://aur.archlinux.org/packages/nohang-git/). Use your favorite [AUR helper](https://wiki.archlinux.org/index.php/AUR_helpers). For example,
```bash
$ yay -S nohang-git
$ sudo systemctl start nohang
$ sudo systemctl enable nohang
```
## How to configure nohang

10
nohang
View File

@ -22,8 +22,10 @@ else:
wait_time = 12
# todo: make config option
max_sleep_time = 2
# todo: make config option
min_sleep_time = 0.1
notify_helper_path = '/usr/sbin/nohang_notify_helper'
@ -34,12 +36,12 @@ psi_support = os.path.exists(psi_path)
HR = '~' * 79
# todo: make config option
print_total_stat = True
##########################################################################
# function definition section
# define functions
def update_stat_dict_and_print(key):
@ -848,8 +850,8 @@ def calculate_percent(arg_key):
# find mem_total
# find positions of SwapFree and SwapTotal in /proc/meminfo
with open('/proc/meminfo') as file:
mem_list = file.readlines()
with open('/proc/meminfo') as f:
mem_list = f.readlines()
mem_list_names = []
for s in mem_list:

394
oom-sort
View File

@ -3,220 +3,228 @@
sort processes by oom_score
"""
# @TODO: user input validation
from operator import itemgetter
from os import listdir
from argparse import ArgumentParser
from time import sleep
def parse_arguments():
"""
parse CLI args
"""
parser = ArgumentParser()
parser.add_argument(
'--num',
'-n',
help="""max number of lines; default: 99999""",
default=99999,
type=int
)
parser.add_argument(
'--len',
'-l',
help="""max cmdline length; default: 99999""",
default=99999,
type=int
)
parser.add_argument(
'--refresh',
'-r',
help='refresh interval (0 to disable); default: 0. '
'Use it with --num/-n to also limit the output length',
default=0,
type=int
)
return parser.parse_args()
"""#######################################################################79"""
def human_readable(num):
# 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):
"""
KiB to MiB
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, ' ')
def clear_screen():
"""
print ANSI sequence to clear the screen
"""
print('\033c')
"""#######################################################################79"""
class TableIndexes: # pylint: disable=too-few-public-methods
"""
table headers from /proc/*/status for further
searching positions of VmRSS and VmSwap in each process output
"""
# parse input
def __init__(self):
with open('/proc/self/status') as status_file:
status_list = status_file.readlines()
status_names = []
for line in status_list:
status_names.append(line.split(':')[0])
self.vm_rss = status_names.index('VmRSS')
self.vm_swap = status_names.index('VmSwap')
self.uid = status_names.index('Uid')
# todo: input validation
INDEX = TableIndexes()
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
class ProcessInfo:
"""#######################################################################79"""
pid = None
cmdline = None
oom_score = None
oom_score_adj = None
# find VmRSS, VmSwap and UID positions in /proc/*/status
name = None
uid = None
vm_rss = None
vm_swap = None
with open('/proc/self/status') as file:
status_list = file.readlines()
@classmethod
def from_pid(cls, pid):
"""
create ProcessInfo instance reading process info from /proc/{pid}/
"""
info = cls()
info.pid = pid
try:
with open('/proc/' + pid + '/cmdline') as file:
try:
info.cmdline = file.readlines()[0].replace('\x00', ' ')
except IndexError:
return None
with open('/proc/' + pid + '/oom_score') as file:
info.oom_score = int(file.readlines()[0][:-1])
with open('/proc/' + pid + '/oom_score_adj') as file:
info.oom_score_adj = int(file.readlines()[0][:-1])
except FileNotFoundError:
return None
except ProcessLookupError:
return None
return info
# список имен из /proc/*/status для дальнейшего поиска позиций VmRSS and VmSwap
status_names = []
for s in status_list:
status_names.append(s.split(':')[0])
def read_status(self):
"""
return True if process have info in /proc/{pid}/status
"""
try:
# @TODO: stop reading file after VmSwap value retrieved
with open('/proc/' + self.pid + '/status') as file:
status_list = file.readlines()
self.vm_rss = int(
status_list[INDEX.vm_rss].split(':')[1].split(' ')[-2]
)
self.vm_swap = int(
status_list[INDEX.vm_swap].split(':')[1].split(' ')[-2]
)
self.name = status_list[0][:-1].split('\t')[1]
self.uid = status_list[INDEX.uid].split('\t')[1]
except FileNotFoundError:
return False
except ProcessLookupError:
return False
return True
vm_rss_index = status_names.index('VmRSS')
vm_swap_index = status_names.index('VmSwap')
uid_index = status_names.index('Uid')
def format_output(self, display_cmdline):
"""
format output for printing
"""
return '{} {} {} {} {} {} M {} M {}'.format(
str(self.oom_score).rjust(9),
str(self.oom_score_adj).rjust(13),
self.uid.rjust(5),
str(self.pid).rjust(5),
self.name.ljust(15),
human_readable(self.vm_rss),
human_readable(self.vm_swap),
self.cmdline[:display_cmdline]
"""#######################################################################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)]
)
class Application:
"""
oom-sort application
"""
oom_list = None
def __init__(self):
args = parse_arguments()
self.num_lines = args.num
self.display_cmdline = args.len
self.refresh_interval = args.refresh
def print_stats(self):
"""
print processes stats sorted by OOM score
"""
oom_list = []
for pid in listdir('/proc'):
# skip non-numeric entries and PID 1
if pid.isdigit() is not True or pid == '1':
continue
proc_info = ProcessInfo.from_pid(pid)
if proc_info:
oom_list.append(proc_info)
oom_list.sort(key=lambda p: p.oom_score, reverse=True)
if self.display_cmdline == 0:
print('oom_score oom_score_adj UID PID Name VmRSS VmSwap')
print('--------- ------------- ----- ----- --------------- -------- --------')
else:
print('oom_score oom_score_adj UID PID Name VmRSS VmSwap cmdline')
print('--------- ------------- ----- ----- --------------- -------- -------- -------')
# iterate through list sorted by oom_score and print name, pid, etc
for proc_info in oom_list[:self.num_lines]:
if proc_info.read_status():
print(
proc_info.format_output(
display_cmdline=self.display_cmdline
)
)
def oom_top(self):
"""
show `top`-like refreshing stats
"""
while True:
try:
clear_screen()
print("Refreshing each {} seconds, press <Ctrl+C> to interrupt:".format(
self.refresh_interval
))
self.print_stats()
sleep(self.refresh_interval)
except KeyboardInterrupt:
break
def main(self):
"""
application entrypoint
"""
if not self.refresh_interval:
self.print_stats()
else:
self.oom_top()
if __name__ == "__main__":
Application().main()
)

222
oom-sort.old Executable file
View File

@ -0,0 +1,222 @@
#!/usr/bin/env python3
"""
sort processes by oom_score
"""
# @TODO: user input validation
from os import listdir
from argparse import ArgumentParser
from time import sleep
def parse_arguments():
"""
parse CLI args
"""
parser = ArgumentParser()
parser.add_argument(
'--num',
'-n',
help="""max number of lines; default: 99999""",
default=99999,
type=int
)
parser.add_argument(
'--len',
'-l',
help="""max cmdline length; default: 99999""",
default=99999,
type=int
)
parser.add_argument(
'--refresh',
'-r',
help='refresh interval (0 to disable); default: 0. '
'Use it with --num/-n to also limit the output length',
default=0,
type=int
)
return parser.parse_args()
def human_readable(num):
"""
KiB to MiB
"""
return str(round(num / 1024.0)).rjust(6, ' ')
def clear_screen():
"""
print ANSI sequence to clear the screen
"""
print('\033c')
class TableIndexes: # pylint: disable=too-few-public-methods
"""
table headers from /proc/*/status for further
searching positions of VmRSS and VmSwap in each process output
"""
def __init__(self):
with open('/proc/self/status') as status_file:
status_list = status_file.readlines()
status_names = []
for line in status_list:
status_names.append(line.split(':')[0])
self.vm_rss = status_names.index('VmRSS')
self.vm_swap = status_names.index('VmSwap')
self.uid = status_names.index('Uid')
INDEX = TableIndexes()
class ProcessInfo:
pid = None
cmdline = None
oom_score = None
oom_score_adj = None
name = None
uid = None
vm_rss = None
vm_swap = None
@classmethod
def from_pid(cls, pid):
"""
create ProcessInfo instance reading process info from /proc/{pid}/
"""
info = cls()
info.pid = pid
try:
with open('/proc/' + pid + '/cmdline') as file:
try:
info.cmdline = file.readlines()[0].replace('\x00', ' ')
except IndexError:
return None
with open('/proc/' + pid + '/oom_score') as file:
info.oom_score = int(file.readlines()[0][:-1])
with open('/proc/' + pid + '/oom_score_adj') as file:
info.oom_score_adj = int(file.readlines()[0][:-1])
except FileNotFoundError:
return None
except ProcessLookupError:
return None
return info
def read_status(self):
"""
return True if process have info in /proc/{pid}/status
"""
try:
# @TODO: stop reading file after VmSwap value retrieved
with open('/proc/' + self.pid + '/status') as file:
status_list = file.readlines()
self.vm_rss = int(
status_list[INDEX.vm_rss].split(':')[1].split(' ')[-2]
)
self.vm_swap = int(
status_list[INDEX.vm_swap].split(':')[1].split(' ')[-2]
)
self.name = status_list[0][:-1].split('\t')[1]
self.uid = status_list[INDEX.uid].split('\t')[1]
except FileNotFoundError:
return False
except ProcessLookupError:
return False
return True
def format_output(self, display_cmdline):
"""
format output for printing
"""
return '{} {} {} {} {} {} M {} M {}'.format(
str(self.oom_score).rjust(9),
str(self.oom_score_adj).rjust(13),
self.uid.rjust(5),
str(self.pid).rjust(5),
self.name.ljust(15),
human_readable(self.vm_rss),
human_readable(self.vm_swap),
self.cmdline[:display_cmdline]
)
class Application:
"""
oom-sort application
"""
oom_list = None
def __init__(self):
args = parse_arguments()
self.num_lines = args.num
self.display_cmdline = args.len
self.refresh_interval = args.refresh
def print_stats(self):
"""
print processes stats sorted by OOM score
"""
oom_list = []
for pid in listdir('/proc'):
# skip non-numeric entries and PID 1
if pid.isdigit() is not True or pid == '1':
continue
proc_info = ProcessInfo.from_pid(pid)
if proc_info:
oom_list.append(proc_info)
oom_list.sort(key=lambda p: p.oom_score, reverse=True)
if self.display_cmdline == 0:
print('oom_score oom_score_adj UID PID Name VmRSS VmSwap')
print('--------- ------------- ----- ----- --------------- -------- --------')
else:
print('oom_score oom_score_adj UID PID Name VmRSS VmSwap cmdline')
print('--------- ------------- ----- ----- --------------- -------- -------- -------')
# iterate through list sorted by oom_score and print name, pid, etc
for proc_info in oom_list[:self.num_lines]:
if proc_info.read_status():
print(
proc_info.format_output(
display_cmdline=self.display_cmdline
)
)
def oom_top(self):
"""
show `top`-like refreshing stats
"""
while True:
try:
clear_screen()
print("Refreshing each {} seconds, press <Ctrl+C> to interrupt:".format(
self.refresh_interval
))
self.print_stats()
sleep(self.refresh_interval)
except KeyboardInterrupt:
break
def main(self):
"""
application entrypoint
"""
if not self.refresh_interval:
self.print_stats()
else:
self.oom_top()
if __name__ == "__main__":
Application().main()

122
oom-sort.old.old Executable file
View File

@ -0,0 +1,122 @@
#!/usr/bin/env python3
"""
sort processes by oom_score
"""
# нужна еще валидация cli ввода
from operator import itemgetter
from os import listdir
from argparse import ArgumentParser
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 == None:
num_lines = 99999
if display_cmdline == None:
display_cmdline = 99999
def human(num):
'''KiB to MiB'''
return str(round(num / 1024.0)).rjust(6, ' ')
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')
oom_list = []
for pid in listdir('/proc'):
# пропускаем элементы, состоящие не из цифр и PID 1
if pid.isdigit() is not True or pid == '1':
continue
try:
with open('/proc/' + pid + '/cmdline') as file:
try:
cmdline = file.readlines()[0].replace('\x00', ' ')
except IndexError:
continue
with open('/proc/' + pid + '/oom_score') as file:
oom_score = int(file.readlines()[0][:-1])
with open('/proc/' + pid + '/oom_score_adj') as file:
oom_score_adj = int(file.readlines()[0][:-1])
except FileNotFoundError:
continue
except ProcessLookupError:
continue
oom_list.append((pid, oom_score, oom_score_adj, cmdline))
# list sorted by oom_score
oom_list_sorted = sorted(oom_list, key=itemgetter(1), reverse=True)
if display_cmdline == '0':
print('oom_score oom_score_adj UID PID Name VmRSS VmSwap')
print('--------- ------------- ----- ----- --------------- -------- --------')
else:
print('oom_score oom_score_adj UID PID Name VmRSS VmSwap cmdline')
print('--------- ------------- ----- ----- --------------- -------- -------- -------')
# итерируемся по сортированному списку oom_score, печатая name, pid etc
for i in oom_list_sorted[:int(num_lines)]:
pid = i[0]
oom_score = i[1]
oom_score_adj = i[2]
cmdline = i[3].strip()
try:
# читать часть файла не дальше VmSwap - когда-нибудь
with open('/proc/' + pid + '/status') as file:
status_list = file.readlines()
vm_rss = int(status_list[vm_rss_index].split(':')[1].split(' ')[-2])
vm_swap = int(status_list[vm_swap_index].split(':')[1].split(' ')[-2])
name = status_list[0][:-1].split('\t')[1]
uid = status_list[uid_index].split('\t')[1]
except FileNotFoundError:
continue
except ProcessLookupError:
continue
print(
'{} {} {} {} {} {} M {} M {}'.format(
str(oom_score).rjust(9),
str(oom_score_adj).rjust(13),
uid.rjust(5),
str(pid).rjust(5),
name.ljust(15),
human(vm_rss),
human(vm_swap),
cmdline[:int(display_cmdline)]
)
)

277
os04 Executable file
View File

@ -0,0 +1,277 @@
#!/usr/bin/env python3
"""
sort processes by oom_score
"""
# REFACTORING IN PROGRESS
from operator import itemgetter
from os import listdir
from argparse import ArgumentParser
"""#######################################################################79"""
# define funtcions
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_name(pid):
"""
Get process name by pid.
pid: str pid of required process
returns string process_name
"""
try:
with open('/proc/' + pid + '/status') as f:
f.seek(6)
for line in f:
return line[:-1]
except FileNotFoundError:
return ''
except ProcessLookupError:
return ''
except UnicodeDecodeError:
with open('/proc/' + pid + '/status', 'rb') as f:
f.seek(6)
return f.read(15).decode(
'utf-8', 'ignore').partition('\n')[0]
def kib_to_mib(num):
"""Convert KiB values to MiB values."""
return round(num / 1024.0)
def human(num):
'''KiB to MiB'''
return str(round(num / 1024.0)).rjust(6, ' ')
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 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]
print(i, 'Name:', name)
if i is uid_index:
uid = f_list[i].split('\t')[2]
print(i, 'UID:', uid)
if i is vm_rss_index:
pass
vm_rss = kib_to_mib(int(f_list[i].split('\t')[1][:-3]))
print(i, 'rss:', vm_rss)
if i is vm_swap_index:
pass
vm_swap = kib_to_mib(int(f_list[i].split('\t')[1][:-3]))
print(i, 'swap:', vm_swap)
"""#######################################################################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
# здесь же искать вообще все.
oom_list = []
for pid in listdir('/proc'):
# пропускаем элементы, состоящие не из цифр и PID 1
if pid.isdigit() is False or pid == '1':
continue
'''
name = pid_to_name(pid)
'''
try:
cmdline = pid_to_cmdline(pid)
if cmdline == '':
continue
with open('/proc/' + pid + '/oom_score') as file:
oom_score = int(file.readlines()[0][:-1])
with open('/proc/' + pid + '/oom_score_adj') as file:
oom_score_adj = int(file.readlines()[0][:-1])
except FileNotFoundError:
continue
except ProcessLookupError:
continue
oom_list.append((pid, oom_score, oom_score_adj, cmdline))
# 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))
# итерируемся по сортированному списку oom_score, печатая name, pid etc
for i in oom_list_sorted[:int(num_lines)]:
pid = i[0]
oom_score = i[1]
oom_score_adj = i[2]
cmdline = i[3]
try:
# читать часть файла не дальше VmSwap - когда-нибудь
with open('/proc/' + pid + '/status') as file:
status_list = file.readlines()
vm_rss = int(status_list[vm_rss_index].split(':')[1].split(' ')[-2])
vm_swap = int(status_list[vm_swap_index].split(':')[1].split(' ')[-2])
name = status_list[0][:-1].split('\t')[1]
uid = status_list[uid_index].split('\t')[1]
except FileNotFoundError:
continue
except ProcessLookupError:
continue
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)]
)
)

326
os05 Executable file
View File

@ -0,0 +1,326 @@
#!/usr/bin/env python3
"""
sort processes by oom_score
"""
# REFACTORING IN PROGRESS
from operator import itemgetter
from os import listdir
from argparse import ArgumentParser
"""#######################################################################79"""
# define funtcions
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_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_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]
print(i, 'Name:', name)
if i is uid_index:
uid = f_list[i].split('\t')[2]
print(i, 'UID:', uid)
if i is vm_rss_index:
pass
vm_rss = kib_to_mib(int(f_list[i].split('\t')[1][:-3]))
print(i, 'rss:', vm_rss)
if i is vm_swap_index:
pass
vm_swap = kib_to_mib(int(f_list[i].split('\t')[1][:-3]))
print(i, 'swap:', 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 pid_to_name(pid):
"""
Get process name by pid.
pid: str pid of required process
returns string process_name
"""
try:
with open('/proc/' + pid + '/status') as f:
f.seek(6)
for line in f:
return line[:-1]
except FileNotFoundError:
return ''
except ProcessLookupError:
return ''
except UnicodeDecodeError:
with open('/proc/' + pid + '/status', 'rb') as f:
f.seek(6)
return f.read(15).decode(
'utf-8', 'ignore').partition('\n')[0]
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, ' ')
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
"""#######################################################################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
'''
name = pid_to_name(pid)
'''
try:
cmdline = pid_to_cmdline(pid)
if cmdline == '':
continue
with open('/proc/' + pid + '/oom_score') as file:
oom_score = int(file.readlines()[0][:-1])
with open('/proc/' + pid + '/oom_score_adj') as file:
oom_score_adj = int(file.readlines()[0][:-1])
except FileNotFoundError:
continue
except ProcessLookupError:
continue
oom_list.append((pid, oom_score, oom_score_adj, cmdline))
# 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))
# итерируемся по сортированному списку oom_score, печатая name, pid etc
for i in oom_list_sorted[:int(num_lines)]:
pid = i[0]
oom_score = i[1]
oom_score_adj = i[2]
cmdline = i[3]
try:
# читать часть файла не дальше VmSwap - когда-нибудь
with open('/proc/' + pid + '/status') as file:
status_list = file.readlines()
vm_rss = int(status_list[vm_rss_index].split(':')[1].split(' ')[-2])
vm_swap = int(status_list[vm_swap_index].split(':')[1].split(' ')[-2])
name = status_list[0][:-1].split('\t')[1]
uid = status_list[uid_index].split('\t')[1]
except FileNotFoundError:
continue
except ProcessLookupError:
continue
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)]
)
)

239
os06 Executable file
View File

@ -0,0 +1,239 @@
#!/usr/bin/env python3
"""
sort processes by oom_score
"""
# REFACTORING IN PROGRESS
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))
# итерируемся по сортированному списку oom_score, печатая name, pid etc
for i in oom_list_sorted[:int(num_lines)]:
pid = i[0]
oom_score = i[1]
oom_score_adj = i[2]
cmdline = i[3]
try:
# читать часть файла не дальше VmSwap - когда-нибудь
with open('/proc/' + pid + '/status') as file:
status_list = file.readlines()
vm_rss = int(status_list[vm_rss_index].split(':')[1].split(' ')[-2])
vm_swap = int(status_list[vm_swap_index].split(':')[1].split(' ')[-2])
name = status_list[0][:-1].split('\t')[1]
uid = status_list[uid_index].split('\t')[1]
except FileNotFoundError:
continue
except ProcessLookupError:
continue
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)]
)
)

220
os07 Executable file
View File

@ -0,0 +1,220 @@
#!/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)]
)
)

222
os08 Executable file
View File

@ -0,0 +1,222 @@
#!/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 = 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((
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)]
)
)
'''