fix oom-sort: fix UnucideDecodeError and fix PID len
This commit is contained in:
parent
fb9f5237ce
commit
15f8a12a02
@ -87,8 +87,13 @@ To uninstall:
|
|||||||
$ sudo make 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
|
## How to configure nohang
|
||||||
|
|
||||||
|
10
nohang
10
nohang
@ -22,8 +22,10 @@ else:
|
|||||||
|
|
||||||
wait_time = 12
|
wait_time = 12
|
||||||
|
|
||||||
|
# todo: make config option
|
||||||
max_sleep_time = 2
|
max_sleep_time = 2
|
||||||
|
|
||||||
|
# todo: make config option
|
||||||
min_sleep_time = 0.1
|
min_sleep_time = 0.1
|
||||||
|
|
||||||
notify_helper_path = '/usr/sbin/nohang_notify_helper'
|
notify_helper_path = '/usr/sbin/nohang_notify_helper'
|
||||||
@ -34,12 +36,12 @@ psi_support = os.path.exists(psi_path)
|
|||||||
|
|
||||||
HR = '~' * 79
|
HR = '~' * 79
|
||||||
|
|
||||||
|
# todo: make config option
|
||||||
print_total_stat = True
|
print_total_stat = True
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
# define functions
|
||||||
# function definition section
|
|
||||||
|
|
||||||
|
|
||||||
def update_stat_dict_and_print(key):
|
def update_stat_dict_and_print(key):
|
||||||
@ -848,8 +850,8 @@ def calculate_percent(arg_key):
|
|||||||
# find mem_total
|
# find mem_total
|
||||||
# find positions of SwapFree and SwapTotal in /proc/meminfo
|
# find positions of SwapFree and SwapTotal in /proc/meminfo
|
||||||
|
|
||||||
with open('/proc/meminfo') as file:
|
with open('/proc/meminfo') as f:
|
||||||
mem_list = file.readlines()
|
mem_list = f.readlines()
|
||||||
|
|
||||||
mem_list_names = []
|
mem_list_names = []
|
||||||
for s in mem_list:
|
for s in mem_list:
|
||||||
|
394
oom-sort
394
oom-sort
@ -3,220 +3,228 @@
|
|||||||
sort processes by oom_score
|
sort processes by oom_score
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# @TODO: user input validation
|
from operator import itemgetter
|
||||||
|
|
||||||
from os import listdir
|
from os import listdir
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
|
|
||||||
def parse_arguments():
|
"""#######################################################################79"""
|
||||||
"""
|
|
||||||
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):
|
# 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, ' ')
|
return str(round(num / 1024.0)).rjust(6, ' ')
|
||||||
|
|
||||||
|
|
||||||
def clear_screen():
|
"""#######################################################################79"""
|
||||||
"""
|
|
||||||
print ANSI sequence to clear the screen
|
|
||||||
"""
|
|
||||||
print('\033c')
|
|
||||||
|
|
||||||
|
|
||||||
class TableIndexes: # pylint: disable=too-few-public-methods
|
# parse input
|
||||||
"""
|
|
||||||
table headers from /proc/*/status for further
|
|
||||||
searching positions of VmRSS and VmSwap in each process output
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self):
|
# todo: input validation
|
||||||
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()
|
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
|
# find VmRSS, VmSwap and UID positions in /proc/*/status
|
||||||
cmdline = None
|
|
||||||
oom_score = None
|
|
||||||
oom_score_adj = None
|
|
||||||
|
|
||||||
name = None
|
with open('/proc/self/status') as file:
|
||||||
uid = None
|
status_list = file.readlines()
|
||||||
vm_rss = None
|
|
||||||
vm_swap = None
|
|
||||||
|
|
||||||
@classmethod
|
# список имен из /proc/*/status для дальнейшего поиска позиций VmRSS and VmSwap
|
||||||
def from_pid(cls, pid):
|
status_names = []
|
||||||
"""
|
for s in status_list:
|
||||||
create ProcessInfo instance reading process info from /proc/{pid}/
|
status_names.append(s.split(':')[0])
|
||||||
"""
|
|
||||||
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):
|
vm_rss_index = status_names.index('VmRSS')
|
||||||
"""
|
vm_swap_index = status_names.index('VmSwap')
|
||||||
return True if process have info in /proc/{pid}/status
|
uid_index = status_names.index('Uid')
|
||||||
"""
|
|
||||||
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):
|
|
||||||
"""
|
"""#######################################################################79"""
|
||||||
format output for printing
|
|
||||||
"""
|
# get sorted list with pid, oom_score, oom_score_adj, cmdline
|
||||||
return '{} {} {} {} {} {} M {} M {}'.format(
|
# get status units: name, uid, rss, swap
|
||||||
str(self.oom_score).rjust(9),
|
|
||||||
str(self.oom_score_adj).rjust(13),
|
|
||||||
self.uid.rjust(5),
|
oom_list = []
|
||||||
str(self.pid).rjust(5),
|
|
||||||
self.name.ljust(15),
|
for pid in listdir('/proc'):
|
||||||
human_readable(self.vm_rss),
|
|
||||||
human_readable(self.vm_swap),
|
# пропускаем элементы, состоящие не из цифр и PID 1
|
||||||
self.cmdline[:display_cmdline]
|
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
222
oom-sort.old
Executable 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
122
oom-sort.old.old
Executable 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
277
os04
Executable 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
326
os05
Executable 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
239
os06
Executable 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
220
os07
Executable 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
222
os08
Executable 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)]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
'''
|
Loading…
Reference in New Issue
Block a user