fix style

This commit is contained in:
Alexey Avramov 2019-04-30 18:33:34 +09:00
parent 3428ac08b4
commit 9b0b15db5b
7 changed files with 3103 additions and 187 deletions

189
nohang
View File

@ -164,23 +164,15 @@ def log(*msg):
print(*msg) print(*msg)
except OSError: except OSError:
sleep(0.01) sleep(0.01)
# print('OSError in print(*msg)')
if separate_log: if separate_log:
# need fix: TypeError: not all arguments converted during string
# formatting
try: try:
info(*msg) info(*msg)
except OSError: except OSError:
sleep(0.01) sleep(0.01)
# print('OSError in info(*msg)')
def print_version(): def print_version():
""" """
сначала пытаться получ версию прямо из гита - вариант для неустановленых,
для тех, кто еще не запускал make install
""" """
try: try:
v = rline1('/etc/nohang/version') v = rline1('/etc/nohang/version')
@ -196,6 +188,7 @@ def print_version():
def test(): def test():
""" """
""" """
print('\n(This option is not ready to use!)\n')
print(version) print(version)
print(argv) print(argv)
@ -229,30 +222,9 @@ def test():
print("pid_to_state('2')") print("pid_to_state('2')")
print(pid_to_state('2')) print(pid_to_state('2'))
'''
print(hr)
print("update_stat_dict_and_print('key')")
print(update_stat_dict_and_print('key'))
print(hr)
print("psi_mem_some_avg_total()")
print(psi_mem_some_avg_total())
print(hr)
print("psi_mem_some_avg10()")
print(psi_mem_some_avg10())
'''
print(hr)
exit() exit()
##########################################################################
def pid_to_cgroup_v1(pid): def pid_to_cgroup_v1(pid):
""" """
""" """
@ -672,12 +644,6 @@ def find_psi_metrics_value(psi_path, psi_metrics):
return float(psi_list[1].split(' ')[3].split('=')[1]) return float(psi_list[1].split(' ')[3].split('=')[1])
def check_mem():
"""find mem_available"""
# исправить название фции
return int(rline1('/proc/meminfo').split(':')[1][:-4])
def check_mem_and_swap(): def check_mem_and_swap():
"""find mem_available, swap_total, swap_free""" """find mem_available, swap_total, swap_free"""
with open('/proc/meminfo') as f: with open('/proc/meminfo') as f:
@ -864,53 +830,6 @@ def send_notify_warn():
Look for process with maximum 'badness' and warn user with notification. Look for process with maximum 'badness' and warn user with notification.
(implement Low memory warnings) (implement Low memory warnings)
""" """
'''
# find process with max badness
fat_tuple = find_victim()
pid = fat_tuple[0]
name = pid_to_name(pid)
if mem_used_zram > 0:
low_mem_percent = '{}% {}% {}%'.format(
round(mem_available / mem_total * 100),
round(swap_free / (swap_total + 0.1) * 100),
round(mem_used_zram / mem_total * 100))
elif swap_free > 0:
low_mem_percent = '{}% {}%'.format(
round(mem_available / mem_total * 100),
round(swap_free / (swap_total + 0.1) * 100))
else:
low_mem_percent = '{}%'.format(
round(mem_available / mem_total * 100))
# title = 'Low memory: {}'.format(low_mem_percent)
title = 'Low memory'
'''
'''
body2 = 'Next victim: {}[{}]'.format(
name.replace(
# symbol '&' can break notifications in some themes,
# therefore it is replaced by '*'
'&', '*'),
pid
)
'''
'''
body = 'MemAvail: {}%\nSwapFree: {}%'.format(
round(mem_available / mem_total * 100),
round(swap_free / (swap_total + 0.1) * 100))
if root: # If nohang was started by root
# send notification to all active users with special script
notify_helper(title, body)
else: # Or by regular user
# send notification to user that runs this nohang
notify_send_wait(title, body)
'''
log('Warning threshold exceeded') log('Warning threshold exceeded')
if check_warning_exe: if check_warning_exe:
@ -1058,7 +977,7 @@ def find_victim(_print_proc_table):
non_decimal_list = get_non_decimal_pids() non_decimal_list = get_non_decimal_pids()
for i in non_decimal_list: for i in non_decimal_list:
if i in pid_list: # ???????????????????????????????????????????? if i in pid_list:
pid_list.remove(i) pid_list.remove(i)
pid_badness_list = [] pid_badness_list = []
@ -1091,9 +1010,11 @@ def find_victim(_print_proc_table):
hr = '#' * 115 hr = '#' * 115
log(hr) log(hr)
log('# PID PPID badness oom_score oom_score_adj eUID S VmSize VmRSS VmSwap Name {}'.format( log('# PID PPID badness oom_score oom_score_adj e'
'UID S VmSize VmRSS VmSwap Name {}'.format(
extra_table_title)) extra_table_title))
log('#------- ------- ------- --------- ------------- ---------- - ------ ----- ------ --------------- --------') log('#------- ------- ------- --------- ------------- -------'
'--- - ------ ----- ------ --------------- --------')
for pid in pid_list: for pid in pid_list:
@ -1327,8 +1248,6 @@ def find_victim_info(pid, victim_badness, name):
'The victim died in the search process: ProcessLookupError') 'The victim died in the search process: ProcessLookupError')
return None return None
# print((time() - status0) * 1000, 'status time')
len_vm = len(str(vm_size)) len_vm = len(str(vm_size))
try: try:
@ -1343,9 +1262,7 @@ def find_victim_info(pid, victim_badness, name):
'The victim died in the search process: FileNotFoundError') 'The victim died in the search process: FileNotFoundError')
return None return None
# te1 = time()
ancestry = pid_to_ancestry(pid, max_ancestry_depth) ancestry = pid_to_ancestry(pid, max_ancestry_depth)
# print((time() - te1) * 1000, 'ms, ancestry')
if detailed_rss: if detailed_rss:
detailed_rss_info = ' (' \ detailed_rss_info = ' (' \
@ -1397,7 +1314,7 @@ def find_victim_info(pid, victim_badness, name):
return victim_info return victim_info
# для дедупликации уведомлений # for warnings deduplication
dick = dict() dick = dict()
dick['v'] = [1, 2, 3, time()] dick['v'] = [1, 2, 3, time()]
@ -1436,19 +1353,12 @@ def implement_corrective_action(signal):
soft_match = False soft_match = False
if soft_actions and signal is SIGTERM: if soft_actions and signal is SIGTERM:
# если мягкий порог И список мягких не пуст:
# итерируемся по списку, ища мэтчинги. Есть совпадения - выполн
# команду и выход из цикла.
name = pid_to_name(pid) name = pid_to_name(pid)
cgroup_v1 = pid_to_cgroup_v1(pid) cgroup_v1 = pid_to_cgroup_v1(pid)
service = '' service = ''
cgroup_v1_tail = cgroup_v1.rpartition('/')[2] cgroup_v1_tail = cgroup_v1.rpartition('/')[2]
# log(cgroup_v1_tail)
if cgroup_v1_tail.endswith('.service'): if cgroup_v1_tail.endswith('.service'):
service = cgroup_v1_tail service = cgroup_v1_tail
# print('$SERVICE:', [service])
# print('ИЩЕМ СОВПАДЕНИЯ ДЛЯ МЯГКИХ ДЕЙСТВИЙ')
# итерируемся по списку кортежей
for i in soft_actions_list: for i in soft_actions_list:
unit = i[0] unit = i[0]
if unit == 'name': if unit == 'name':
@ -1457,10 +1367,9 @@ def implement_corrective_action(signal):
u = cgroup_v1 u = cgroup_v1
regexp = i[1] regexp = i[1]
command = i[2] command = i[2]
# print([u, regexp, command])
if search(regexp, u) is not None: if search(regexp, u) is not None:
log("Regexp '{}' matches with {} '{}'".format(regexp, unit, u)) log("Regexp '{}' matches with {} '{}'".format(
# print('СОВПАДЕНИЕ НАЙДЕНО') regexp, unit, u))
soft_match = True soft_match = True
break break
@ -1552,10 +1461,6 @@ def implement_corrective_action(signal):
exe(cmd) exe(cmd)
if gui_notifications: if gui_notifications:
# min delay after same notification
# все не так. От этого вообще пол дедупликация . терминация
# один раз покажется при любом раскладе.
delay_after_same_notify = 1 delay_after_same_notify = 1
x = dick['v'] x = dick['v']
@ -1567,11 +1472,7 @@ def implement_corrective_action(signal):
# print(y[3] - x[3]) # print(y[3] - x[3])
if x[0] == y[0] and x[1] == y[1] and x[2] == y[2]: if x[0] == y[0] and x[1] == y[1] and x[2] == y[2]:
# print('совпадение имени, пид, сигнала')
# сохр в словаре первре совпавшее время
dt = y[3] - x[3] dt = y[3] - x[3]
# print(dt, 'dt')
if dt < delay_after_same_notify: if dt < delay_after_same_notify:
notif = False notif = False
@ -1669,7 +1570,7 @@ def sleep_after_check_mem():
try: try:
stdout.flush() stdout.flush()
except OSError: # OSError: [Errno 105] No buffer space available except OSError:
pass pass
sleep(t) sleep(t)
@ -1741,8 +1642,6 @@ def calculate_percent(arg_key):
print_proc_table_flag = False print_proc_table_flag = False
# print(len(argv), argv)
if len(argv) == 1: if len(argv) == 1:
if os.path.exists('./nohang.conf'): if os.path.exists('./nohang.conf'):
config = os.getcwd() + '/nohang.conf' config = os.getcwd() + '/nohang.conf'
@ -1887,8 +1786,6 @@ try:
if etc: if etc:
# это остаток строки без первого ключа. Содержит: регулярка ///
# команда
a = line.partition('@SOFT_ACTION_RE_NAME')[ a = line.partition('@SOFT_ACTION_RE_NAME')[
2].partition(opt_separator) 2].partition(opt_separator)
@ -1901,14 +1798,10 @@ try:
zzz = (a1, a2, a3) zzz = (a1, a2, a3)
# print(zzz)
soft_actions_list.append(zzz) soft_actions_list.append(zzz)
if etc2: if etc2:
# это остаток строки без первого ключа. Содержит: регулярка ///
# команда
a = line.partition('@SOFT_ACTION_RE_CGROUP_V1')[ a = line.partition('@SOFT_ACTION_RE_CGROUP_V1')[
2].partition(opt_separator) 2].partition(opt_separator)
@ -1921,8 +1814,6 @@ try:
zzz = (a1, a2, a3) zzz = (a1, a2, a3)
# print(zzz)
soft_actions_list.append(zzz) soft_actions_list.append(zzz)
if line.startswith('@PROCESSNAME_RE'): if line.startswith('@PROCESSNAME_RE'):
@ -2040,16 +1931,16 @@ else:
re_match_cgroup_v2 = True re_match_cgroup_v2 = True
# print(processname_re_list) print(processname_re_list)
# print(cmdline_re_list) print(cmdline_re_list)
# print(uid_re_list) print(uid_re_list)
# print(environ_re_list) print(environ_re_list)
# print(realpath_re_list) print(realpath_re_list)
# print(cgroup_v1_re_list) print(cgroup_v1_re_list)
# print(cgroup_v2_re_list) print(cgroup_v2_re_list)
# print(soft_actions_list) print(soft_actions_list)
if soft_actions_list == []: if soft_actions_list == []:
soft_actions = False soft_actions = False
@ -2077,21 +1968,6 @@ gui_notifications = conf_parse_bool('gui_notifications')
decrease_oom_score_adj = conf_parse_bool('decrease_oom_score_adj') decrease_oom_score_adj = conf_parse_bool('decrease_oom_score_adj')
ignore_psi = conf_parse_bool('ignore_psi') ignore_psi = conf_parse_bool('ignore_psi')
# regex_matching = conf_parse_bool('regex_matching')
# re_match_cmdline = conf_parse_bool('re_match_cmdline')
# re_match_uid = conf_parse_bool('re_match_uid')
# re_match_cgroup_v1 = conf_parse_bool('re_match_cgroup_v1')
# re_match_cgroup_v2 = conf_parse_bool('re_match_cgroup_v2')
# re_match_realpath = conf_parse_bool('re_match_realpath')
# re_match_environ = conf_parse_bool('re_match_environ')
# if regex_matching or re_match_cmdline or re_match_uid or re_match_cgroup
# or re_match_realpath:
# from re import search
# from sre_constants import error as invalid_re
(mem_min_sigterm_kb, mem_min_sigterm_mb, mem_min_sigterm_percent (mem_min_sigterm_kb, mem_min_sigterm_mb, mem_min_sigterm_percent
) = calculate_percent('mem_min_sigterm') ) = calculate_percent('mem_min_sigterm')
@ -2469,9 +2345,6 @@ psi_support = os.path.exists(psi_path)
# Get KiB levels if it's possible. # Get KiB levels if it's possible.
# получ кб. если не кб - то процент. Если процент - находим кб ниже на
# основе полученного своптотал и процентов.
def get_swap_threshold_tuple(string): def get_swap_threshold_tuple(string):
# re (Num %, True) or (Num KiB, False) # re (Num %, True) or (Num KiB, False)
@ -2570,7 +2443,6 @@ if print_config:
print('min_delay_after_sigkill: {}'.format(min_delay_after_sigkill)) print('min_delay_after_sigkill: {}'.format(min_delay_after_sigkill))
print('min_badness: {}'.format(min_badness)) print('min_badness: {}'.format(min_badness))
# False (OK) - OK не нужен когда фолс
print('decrease_oom_score_adj: {}'.format( print('decrease_oom_score_adj: {}'.format(
decrease_oom_score_adj decrease_oom_score_adj
)) ))
@ -2633,14 +2505,11 @@ warn_timer = 0
########################################################################## ##########################################################################
if not root: if not root:
log('WARNING: effective UID != 0; euid={}; processes with other e' log('WARNING: effective UID != 0; euid={}; processes with other e'
'uids will be invisible for nohang'.format(self_uid)) 'uids will be invisible for nohang'.format(self_uid))
# Try to lock all memory # Try to lock all memory
mlockall() mlockall()
@ -2648,13 +2517,9 @@ mlockall()
########################################################################## ##########################################################################
print_self_rss() print_self_rss()
# if print_proc_table:
# find_victim(print_proc_table)
log('Monitoring has started!') log('Monitoring has started!')
stdout.flush() stdout.flush()
@ -2739,10 +2604,6 @@ while True:
mem_available, swap_total, swap_free = check_mem_and_swap() mem_available, swap_total, swap_free = check_mem_and_swap()
# print(mem_available, swap_total, swap_free)
# если метры - получаем киб выше и сразу. см.
# if swap_min_sigkill is set in percent # if swap_min_sigkill is set in percent
if swap_kill_is_percent: if swap_kill_is_percent:
swap_min_sigkill_kb = swap_total * swap_min_sigkill_percent / 100.0 swap_min_sigkill_kb = swap_total * swap_min_sigkill_percent / 100.0
@ -2753,9 +2614,6 @@ while True:
if swap_warn_is_percent: if swap_warn_is_percent:
swap_min_warnings_kb = swap_total * swap_min_warnings_percent / 100.0 swap_min_warnings_kb = swap_total * swap_min_warnings_percent / 100.0
# в общем случае для работы нужны килобайты. Если в процентах задано -
# находим КБ тут, после получения своптотал.
mem_used_zram = check_zram() mem_used_zram = check_zram()
if print_mem_check_results: if print_mem_check_results:
@ -2825,8 +2683,7 @@ while True:
) )
) )
# если swap_min_sigkill задан в абсолютной величине и Swap_total = 0 if swap_total > swap_min_sigkill_kb:
if swap_total > swap_min_sigkill_kb: # If swap_min_sigkill is absolute
swap_sigkill_pc = percent(swap_min_sigkill_kb / (swap_total + 0.1)) swap_sigkill_pc = percent(swap_min_sigkill_kb / (swap_total + 0.1))
else: else:
swap_sigkill_pc = '-' swap_sigkill_pc = '-'
@ -2834,14 +2691,8 @@ while True:
if swap_total > swap_min_sigterm_kb: if swap_total > swap_min_sigterm_kb:
swap_sigterm_pc = percent(swap_min_sigterm_kb / (swap_total + 0.1)) swap_sigterm_pc = percent(swap_min_sigterm_kb / (swap_total + 0.1))
else: else:
# печатать так: SwapTotal = 0, ignore swapspace
swap_sigterm_pc = '-' swap_sigterm_pc = '-'
# это для печати меминфо. Все переработать нахрен.
# далее пошла проверка превышения порогов
# MEM SWAP KILL # MEM SWAP KILL
if (mem_available <= mem_min_sigkill_kb and if (mem_available <= mem_min_sigkill_kb and
swap_free <= swap_min_sigkill_kb): swap_free <= swap_min_sigkill_kb):
@ -2898,8 +2749,6 @@ while True:
kib_to_mib(mem_available), kib_to_mib(mem_available),
percent(mem_available / mem_total), percent(mem_available / mem_total),
kib_to_mib(mem_min_sigterm_kb), kib_to_mib(mem_min_sigterm_kb),
# percent(mem_min_sigterm_kb / mem_total),
# ОКРУГЛЯТЬ НА МЕСТЕ ВЫШЕ (или не выше, хз)
round(mem_min_sigterm_percent, 1), round(mem_min_sigterm_percent, 1),
kib_to_mib(swap_free), kib_to_mib(swap_free),
percent(swap_free / (swap_total + 0.1)), percent(swap_free / (swap_total + 0.1)),

View File

@ -142,7 +142,7 @@ min_badness = 20
Valid values are non-negative floating-point numbers. Valid values are non-negative floating-point numbers.
min_delay_after_sigterm = 0.2 min_delay_after_sigterm = 1
min_delay_after_sigkill = 1 min_delay_after_sigkill = 1
Valid values are True and False. Valid values are True and False.

View File

@ -8,7 +8,7 @@ from operator import itemgetter
from os import listdir from os import listdir
from argparse import ArgumentParser from argparse import ArgumentParser
"""#######################################################################79""" ##########################################################################
# define funtcions # define funtcions
@ -63,7 +63,7 @@ def get_max_pid_len():
return len(line.strip()) return len(line.strip())
"""#######################################################################79""" ##########################################################################
sort_dict = { sort_dict = {
@ -78,7 +78,7 @@ sort_dict = {
} }
"""#######################################################################79""" ##########################################################################
# parse CLI args # parse CLI args
@ -129,7 +129,7 @@ if sort_by not in sort_dict:
exit() exit()
"""#######################################################################79""" ##########################################################################
# find VmRSS, VmSwap and UID positions in /proc/*/status for further # find VmRSS, VmSwap and UID positions in /proc/*/status for further
# searching positions of UID, VmRSS and VmSwap in each process # searching positions of UID, VmRSS and VmSwap in each process
@ -146,7 +146,7 @@ vm_rss_index = status_names.index('VmRSS')
vm_swap_index = status_names.index('VmSwap') vm_swap_index = status_names.index('VmSwap')
"""#######################################################################79""" ##########################################################################
# get sorted list with pid, oom_score, oom_score_adj, cmdline # get sorted list with pid, oom_score, oom_score_adj, cmdline
# get status units: name, uid, rss, swap # get status units: name, uid, rss, swap
@ -187,7 +187,7 @@ oom_list_sorted = sorted(
oom_list, key=itemgetter(int(sort_dict[sort_by])), reverse=True) oom_list, key=itemgetter(int(sort_dict[sort_by])), reverse=True)
"""#######################################################################79""" ##########################################################################
# find width of columns # find width of columns
@ -206,7 +206,7 @@ if max_vm_rss_len < 5:
max_vm_rss_len = 5 max_vm_rss_len = 5
"""#######################################################################79""" ##########################################################################
# print output # print output

2946
trash/nohang 0.2 rc1 Executable file

File diff suppressed because it is too large Load Diff

View File

@ -6,13 +6,13 @@ from memco import *
from signal import signal, SIGTERM from signal import signal, SIGTERM
from time import sleep from time import sleep
from sys import exit
def signal_handler(signum, frame): def signal_handler(signum, frame):
print('Got signal {}'.format(signum)) print('Got signal {}'.format(signum))
# sleep(1) # sleep(1)
exit() # exit()
signal(SIGTERM, signal_handler) signal(SIGTERM, signal_handler)

View File

@ -116,13 +116,10 @@ print('Name:', name)
print('RSS at startup: {} (100.0 %)'.format(int(rss0))) print('RSS at startup: {} (100.0 %)'.format(int(rss0)))
print('MemAvail:', ma) print('MemAvail:', ma)
send_signal = SIGKILL send_signal = SIGTERM
os.kill(int(pid), SIGCONT)
# os.kill(int(pid), SIGCONT)
os.kill(int(pid), send_signal) os.kill(int(pid), send_signal)

124
trash/x01 Executable file
View File

@ -0,0 +1,124 @@
#!/usr/bin/env python3
from os import getpid
# find mem_total
# find positions of SwapFree and SwapTotal in /proc/meminfo
with open('/proc/meminfo') as f:
mem_list = f.readlines()
mem_list_names = []
for s in mem_list:
mem_list_names.append(s.split(':')[0])
if mem_list_names[2] != 'MemAvailable':
errprint('WARNING: Your Linux kernel is too old, Linux 3.14+ requied')
# exit(1)
swap_total_index = mem_list_names.index('SwapTotal')
swap_free_index = swap_total_index + 1
mem_total = int(mem_list[0].split(':')[1][:-4])
# Get names from /proc/*/status to be able to get VmRSS and VmSwap values
with open('/proc/self/status') as file:
status_list = file.readlines()
status_names = []
for s in status_list:
status_names.append(s.split(':')[0])
ppid_index = status_names.index('PPid')
vm_size_index = status_names.index('VmSize')
vm_rss_index = status_names.index('VmRSS')
vm_swap_index = status_names.index('VmSwap')
uid_index = status_names.index('Uid')
state_index = status_names.index('State')
try:
anon_index = status_names.index('RssAnon')
file_index = status_names.index('RssFile')
shmem_index = status_names.index('RssShmem')
detailed_rss = True
# print(detailed_rss, 'detailed_rss')
except ValueError:
detailed_rss = False
# print('It is not Linux 4.5+')
self_pid = str(getpid())
def self_rss():
r = pid_to_status(self_pid)[5]
print(r)
def pid_to_status(pid):
"""
"""
try:
with open('/proc/' + pid + '/status') as f:
for n, line in enumerate(f):
if n is 0:
name = line.split('\t')[1][:-1]
if n is state_index:
state = line.split('\t')[1][0]
continue
if n is ppid_index:
ppid = line.split('\t')[1][:-1]
continue
if n is uid_index:
uid = line.split('\t')[2]
continue
if n is vm_size_index:
vm_size = int(line.split('\t')[1][:-4])
continue
if n is vm_rss_index:
vm_rss = int(line.split('\t')[1][:-4])
continue
if n is vm_swap_index:
vm_swap = int(line.split('\t')[1][:-4])
break
return name, state, ppid, uid, vm_size, vm_rss, vm_swap
except UnicodeDecodeError:
return pid_to_status_unicode(pid)
except FileNotFoundError:
return None
except ProcessLookupError:
return None
except ValueError:
return None
self_rss()
import logging
import subprocess
import argparse
self_rss()