From 9e4135a4020616896bccbdefa8dc8f4ca0686381 Mon Sep 17 00:00:00 2001 From: pushsla Date: Sat, 24 Nov 2018 14:11:38 +0300 Subject: [PATCH] pep8, comment transtations, defines --- nohang | 692 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 395 insertions(+), 297 deletions(-) diff --git a/nohang b/nohang index 0eba8f6..c079dcf 100755 --- a/nohang +++ b/nohang @@ -1,7 +1,5 @@ -#!/usr/bin/env python3 - -# A daemon that prevents out of memory - +#!/usr/bin/python +"""A daemon that prevents OOM in linux systems.""" import os import signal from operator import itemgetter @@ -11,7 +9,7 @@ from sys import stdout sig_dict = {signal.SIGKILL: 'SIGKILL', - signal.SIGTERM: 'SIGTERM'} + signal.SIGTERM: 'SIGTERM'} # directory where the script is running cd = os.getcwd() @@ -42,17 +40,19 @@ zram_disksize_factor = 0.0042 # function definition section -# return list of tuples with -# username, DISPLAY and DBUS_SESSION_BUS_ADDRESS def root_notify_env(): + """ + Get environment for notification sending from root. + Returns list [tuple username, tuple DISPLAY, tuple DBUS_SESSION_BUS_ADDRES] + """ ps_output_list = Popen(['ps', 'ae'], stdout=PIPE - ).communicate()[0].decode().split('\n') + ).communicate()[0].decode().split('\n') lines_with_displays = [] for line in ps_output_list: if ' DISPLAY=' in line and ' DBUS_SESSION_BUS_ADDRES' \ - 'S=' in line and ' USER=' in line: + 'S=' in line and ' USER=' in line: lines_with_displays.append(line) # list of tuples with needments @@ -79,6 +79,7 @@ def root_notify_env(): def string_to_float_convert_test(string): + """Try to interprete string values as floats.""" try: return float(string) except ValueError: @@ -86,6 +87,7 @@ def string_to_float_convert_test(string): def string_to_int_convert_test(string): + """Try to interpretst string values as integers.""" try: return int(string) except ValueError: @@ -94,6 +96,12 @@ def string_to_int_convert_test(string): # extracting the parameter from the config dictionary, str return def conf_parse_string(param): + """ + Get string parameters from the config dict. + + param: config_dict key + returns config_dict[param].strip() + """ if param in config_dict: return config_dict[param].strip() else: @@ -104,6 +112,12 @@ def conf_parse_string(param): # extracting the parameter from the config dictionary, bool return def conf_parse_bool(param): + """ + Get bool parameters from the config_dict. + + param: config_dicst key + returns bool + """ if param in config_dict: param_str = config_dict[param] if param_str == 'True': @@ -122,6 +136,9 @@ def conf_parse_bool(param): def func_decrease_oom_score_adj(oom_score_adj_max): + """ + Pls, put description here... + """ for i in os.listdir('/proc'): if i.isdigit() is not True: continue @@ -136,28 +153,31 @@ def func_decrease_oom_score_adj(oom_score_adj_max): pass -# read 1st line def rline1(path): + """read 1st line from path.""" with open(path) as f: for line in f: return line[:-1] -# write in file def write(path, string): + """Write string to path.""" with open(path, 'w') as f: f.write(string) def kib_to_mib(num): + """Convert Kib values to Mib values.""" return round(num / 1024.0) def percent(num): + """Interprete mum as percentage.""" return round(num * 100, 1) def just_percent_mem(num): + """Pls, put description here...""" return str(round(num * 100, 1)).rjust(4, ' ') @@ -167,11 +187,18 @@ def just_percent_swap(num): # KiB to MiB, right alignment def human(num, lenth): + """Convert Kib values to Mib values with right alignment""" return str(round(num / 1024)).rjust(lenth, ' ') # return str with amount of bytes def zram_stat(zram_id): + """ + Get zram state. + + zram_id: str zram block-device id + returns bytes diskcize, str mem_used_total + """ try: disksize = rline1('/sys/block/' + zram_id + '/disksize') except FileNotFoundError: @@ -192,6 +219,12 @@ def zram_stat(zram_id): # return process name 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: for line in f: @@ -203,7 +236,11 @@ def pid_to_name(pid): def send_notify_warn(): + """ + Look for process with maximum 'badness' and warn user with notification. + + """ # find process with max badness fat_tuple = fattest() pid = fat_tuple[1] @@ -225,20 +262,29 @@ def send_notify_warn(): title = 'Low memory: {}'.format(low_mem_percent) body = 'Fattest process: {}, {}'.format(pid, name) - if root: - # send notification to all active users - Popen(['/usr/sbin/nohang_notify_low_mem', '--mem', low_mem_percent, '--pid', pid, '--name', name]) - else: - # отправляем уведомление пользователю, который запустил nohang - Popen(['notify-send', '--icon=dialog-warning', 'Low memory: {}'.format(title), '{}'.format(body)]) + if root: # If nohang was started by root + # send notification to all active users with special script + Popen(['/usr/sbin/nohang_notify_low_mem', '--mem', low_mem_percent, + '--pid', pid, '--name', name]) + else: # Or by regular user + # send notification to user that runs this nohang + Popen(['notify-send', '--icon=dialog-warning', + 'Low memory: {}'.format(title), '{}'.format(body)]) def send_notify(signal, name, pid): + """ + Notificate about OOM Preventing. + + signal: key for notify_sig_dict + name: str process name + pid: str process pid + """ title = 'Preventing OOM' body = '{} process {}, {}'.format( notify_sig_dict[signal], pid, name.replace('&', '*')) if root: - # отправляем уведомление всем залогиненным пользователям + # send notification to all active users with notify-send b = root_notify_env() if len(b) > 0: for i in b: @@ -247,16 +293,23 @@ def send_notify(signal, name, pid): dbus_env, 'notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)]) else: - # отправляем уведомление пользователю, который запустил nohang + # send notification to user that runs this nohang Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)]) def send_notify_etc(pid, name, command): + """ + Notificate about OOM Preventing. + + command: str command that will be executed + name: str process name + pid: str process pid + """ title = 'Preventing OOM' body = 'Victim is process {}, {}\nExecute the command:\n{}'.format( pid, name.replace('&', '*'), command.replace('&', '*')) if root: - # отправляем уведомление всем залогиненным пользователям + # send notification to all active users with notify-send b = root_notify_env() if len(b) > 0: for i in b: @@ -265,11 +318,17 @@ def send_notify_etc(pid, name, command): dbus_env, 'notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)]) else: - # отправляем уведомление пользователю, который запустил nohang - Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)]) + # send notification to user that runs this nohang + Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}' + .format(body)]) def sleep_after_send_signal(signal): + """ + Sleeping after signal was sent. + + signal: sent signal + """ if signal is signal.SIGKILL: if print_sleep_periods: print(' sleep', min_delay_after_sigkill) @@ -281,7 +340,11 @@ def sleep_after_send_signal(signal): def find_victim_and_send_signal(signal): + """ + Please describe this. + thanks + """ if decrease_oom_score_adj and root: func_decrease_oom_score_adj(oom_score_adj_max) @@ -322,23 +385,19 @@ def find_victim_and_send_signal(signal): badness = 0 pid_badness_list.append((pid, badness)) - - # получаем отсортированный по badness список пар (pid, badness) + # Make list of (pid, badness) tuples, sorted by 'badness' values pid_tuple_list = sorted( pid_badness_list, key=itemgetter(1), reverse=True)[0] - # получаем максимальный badness + # Get maximum 'badness' value victim_badness = pid_tuple_list[1] - if victim_badness >= min_badness: - - # пытаемся отправить сигнал найденной жертве + if victim_badness >= min_badness: # Try to send signal to found victim pid = pid_tuple_list[0] - name = pid_to_name(pid) - # находим VmRSS и VmSwap процесса, которому попытаемся послать сигнал + # Get VmRSS and VmSwap of victim process and try to send signal try: with open('/proc/' + pid + '/status') as f: for n, line in enumerate(f): @@ -367,7 +426,12 @@ def find_victim_and_send_signal(signal): command = etc_dict[name] exit_status = os.system(etc_dict[name]) response_time = time() - time0 - etc_info = ' Finding the process with the highest badness\n Victim is {}, pid: {}, badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Execute the command: {}\n Exit status: {}; response time: {} ms'.format(name, pid, victim_badness, vm_rss, vm_swap, command, exit_status, round(response_time * 1000)) + etc_info = ''' Finding the process with the highest badness\n + Victim is {}, pid:{}, badness:{}, VmRSS: {} MiB, VmSwap: {} MiB\n + Execute the command: {}\n + Exit status: {}; response time: {} ms'''.format( + name, pid, victim_badness, vm_rss, vm_swap, command, + exit_status, round(response_time * 1000)) print(mem_info) print(etc_info) if gui_notifications: @@ -390,6 +454,7 @@ def find_victim_and_send_signal(signal): response_time = time() - time0 send_result = 'no such process; response time: {} ms'.format(round(response_time * 1000)) + # Pls correct line length =) preventing_oom_message = ' Finding the process with the highest badness\n Victim is {}, pid: {}, badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Sending {} to the victim; {}'.format(name, pid, victim_badness, vm_rss, vm_swap, sig_dict[signal], send_result) print(mem_info) print(preventing_oom_message) @@ -407,7 +472,7 @@ def find_victim_and_send_signal(signal): def sleep_after_check_mem(): - # задание периода сна в зависимости от рейтов и уровней доступной памяти + """Specify sleep times depends on rates and avialable memory.""" t_mem = mem_available / rate_mem t_swap = swap_free / rate_swap t_zram = (mem_total - mem_used_zram) / rate_zram @@ -429,8 +494,8 @@ def sleep_after_check_mem(): exit() - def fattest(): + """Find the 'fattest' process""" pid_badness_list = [] if regex_matching: @@ -468,8 +533,7 @@ def fattest(): badness = 0 pid_badness_list.append((pid, badness)) - - # получаем отсортированный по badness список пар (pid, badness) + # Make list of (pid, badness) tuples, sorted by 'badness' values pid_tuple_list = sorted( pid_badness_list, key=itemgetter(1), reverse=True)[0] @@ -480,12 +544,10 @@ def fattest(): return (name, pid) - ########################################################################## # поиск позиций и mem_total - with open('/proc/meminfo') as file: mem_list = file.readlines() @@ -505,7 +567,7 @@ mem_total = int(mem_list[0].split(':')[1].strip(' kB\n')) with open('/proc/self/status') as file: status_list = file.readlines() -# список имен из /proc/*/status для дальнейшего поиска позиций VmRSS and VmSwap +# Get names from /proc/*/status to be able to get VmRSS and VmSwap values status_names = [] for s in status_list: status_names.append(s.split(':')[0]) @@ -515,9 +577,9 @@ vm_swap_index = status_names.index('VmSwap') ########################################################################## -# получение пути к конфигу +# Configurations -# парсинг аргументов командной строки +# Cmd argparse parser = ArgumentParser() parser.add_argument( '-c', @@ -541,7 +603,7 @@ if arg_config is None: config = i break if config is None: - print('По дефолтным путям конфиг не найден\n', conf_err_mess) + print('Default configuration was not found\n', conf_err_mess) exit() else: @@ -625,7 +687,6 @@ print_sleep_periods = conf_parse_bool('print_sleep_periods') realtime_ionice = conf_parse_bool('realtime_ionice') - if 'realtime_ionice_classdata' in config_dict: realtime_ionice_classdata = string_to_int_convert_test( config_dict['realtime_ionice_classdata']) @@ -654,7 +715,7 @@ if 'niceness' in config_dict: print('Invalid niceness value, not integer\nExit') exit() if niceness < -20 or niceness > 19: - print('Недопустимое значение niceness\nExit') + print('niceness out of range [-20; 19]\nExit') exit() else: print('niceness not in config\nExit') @@ -668,7 +729,7 @@ if 'oom_score_adj' in config_dict: print('Invalid oom_score_adj value, not integer\nExit') exit() if oom_score_adj < -1000 or oom_score_adj > 1000: - print('Недопустимое значение oom_score_adj\nExit') + print('oom_score_adj out of range [-1000; 1000]\nExit') exit() else: print('oom_score_adj not in config\nExit') @@ -681,7 +742,7 @@ if 'rate_mem' in config_dict: print('Invalid rate_mem value, not float\nExit') exit() if rate_mem <= 0: - print('rate_mem должен быть положительным\nExit') + print('rate_mem MUST be > 0\nExit') exit() else: print('rate_mem not in config\nExit') @@ -694,7 +755,7 @@ if 'rate_swap' in config_dict: print('Invalid rate_swap value, not float\nExit') exit() if rate_swap <= 0: - print('rate_swap должен быть положительным\nExit') + print('rate_swap MUST be > 0\nExit') exit() else: print('rate_swap not in config\nExit') @@ -707,94 +768,149 @@ if 'rate_zram' in config_dict: print('Invalid rate_zram value, not float\nExit') exit() if rate_zram <= 0: - print('rate_zram должен быть положительным\nExit') + print('rate_zram MUST be > 0\nExit') exit() else: print('rate_zram not in config\nExit') exit() -if 'mem_min_sigterm' in config_dict: - mem_min_sigterm = config_dict['mem_min_sigterm'] +def calculate_percent(arg_key): + """ + Calculate mem_min_KEY_percent. - if mem_min_sigterm.endswith('%'): - # отбрасываем процент, получаем число - mem_min_sigterm_percent = mem_min_sigterm[:-1].strip() - # далее флоат тест - mem_min_sigterm_percent = string_to_float_convert_test(mem_min_sigterm_percent) - if mem_min_sigterm_percent is None: - print('Invalid mem_min_sigterm value, not float\nExit') - exit() - # окончательная валидация - if mem_min_sigterm_percent < 0 or mem_min_sigterm_percent > 100: - print('mem_min_sigterm, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit') - exit() + Try use this one) + arg_key: str key for config_dict + returns int mem_min_percent or NoneType if got some error + """ + global mem_total + global string_to_float_convert_test + global config_dict - # mem_min_sigterm_percent это теперь чистое валидное флоат число процентов, можно переводить в кб - mem_min_sigterm_kb = mem_min_sigterm_percent / 100 * mem_total - mem_min_sigterm_mb = round(mem_min_sigterm_kb / 1024) + if arg_key in config_dict: + mem_min = config_dict[arg_key] - elif mem_min_sigterm.endswith('M'): - mem_min_sigterm_mb = string_to_float_convert_test(mem_min_sigterm[:-1].strip()) - if mem_min_sigterm_mb is None: - print('Invalid mem_min_sigterm value, not float\nExit') - exit() - mem_min_sigterm_kb = mem_min_sigterm_mb * 1024 - if mem_min_sigterm_kb > mem_total: - print('mem_min_sigterm value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) - exit() - mem_min_sigterm_percent = mem_min_sigterm_kb / mem_total * 100 + if mem_min.endswith('%'): + # truncate percents, so we have a number + mem_min_percent = mem_min[:-1].strip() + # then 'float test' + mem_min_percent = string_to_float_convert_test(mem_min_percent) + if mem_min_percent is None: + print('Invalid {} value, not float\nExit'.format(arg_key)) + exit() + # Final validations... + if mem_min_percent < 0 or mem_min_percent > 100: + print('{}, as percents value, out of range [0; 100]\nExit'.format(arg_key)) + exit() + + # mem_min_sigterm_percent is clean and valid float percentage. Can translate into Kb + mem_min_kb = mem_min_percent / 100 * mem_total + mem_min_mb = round(mem_min_sigterm_kb / 1024) + + elif mem_min.endswith('M'): + mem_min_mb = string_to_float_convert_test(mem_min[:-1].strip()) + if mem_min_mb is None: + print('Invalid {} value, not float\nExit'.format(arg_key)) + exit() + mem_min_kb = mem_min_mb * 1024 + if mem_min_kb > mem_total: + print('{} value can not be greater then MemTotal ({} MiB)\nExit'.format(arg_key, round(mem_total / 1024))) + exit() + mem_min_percent = mem_min_kb / mem_total * 100 + + else: + print('Invalid {} units in config.\n Exit'.format(arg_key)) + mem_min_percent = None else: - print('Конфиг инвалид, для mem_min_sigterm неверно указаны единицы измерения\nExit') - exit() + print('{} not in config\nExit'.format(arg_key)) + mem_min_percent = None -else: - print('mem_min_sigterm not in config\nExit') - exit() + return mem_min_percent -if 'mem_min_sigkill' in config_dict: - mem_min_sigkill = config_dict['mem_min_sigkill'] +# if 'mem_min_sigterm' in config_dict: +# mem_min_sigterm = config_dict['mem_min_sigterm'] - if mem_min_sigkill.endswith('%'): - # отбрасываем процент, получаем число - mem_min_sigkill_percent = mem_min_sigkill[:-1].strip() - # далее флоат тест - mem_min_sigkill_percent = string_to_float_convert_test(mem_min_sigkill_percent) - if mem_min_sigkill_percent is None: - print('Invalid mem_min_sigkill value, not float\nExit') - exit() - # окончательная валидация - if mem_min_sigkill_percent < 0 or mem_min_sigkill_percent > 100: - print('mem_min_sigkill, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit') - exit() +# if mem_min_sigterm.endswith('%'): +# # truncate percents, so we have a number +# mem_min_sigterm_percent = mem_min_sigterm[:-1].strip() +# # then 'float test' +# mem_min_sigterm_percent = string_to_float_convert_test(mem_min_sigterm_percent) +# if mem_min_sigterm_percent is None: +# print('Invalid mem_min_sigterm value, not float\nExit') +# exit() +# # Final validations... +# if mem_min_sigterm_percent < 0 or mem_min_sigterm_percent > 100: +# print('mem_min_sigterm, as percents value, out of range [0; 100]\nExit') +# exit() - # mem_min_sigterm_percent это теперь чистое валидное флоат число процентов, можно переводить в кб - mem_min_sigkill_kb = mem_min_sigkill_percent / 100 * mem_total - mem_min_sigkill_mb = round(mem_min_sigkill_kb / 1024) +# # mem_min_sigterm_percent is clean and valid float percentage. Can translate into Kb +# mem_min_sigterm_kb = mem_min_sigterm_percent / 100 * mem_total +# mem_min_sigterm_mb = round(mem_min_sigterm_kb / 1024) - elif mem_min_sigkill.endswith('M'): - mem_min_sigkill_mb = string_to_float_convert_test(mem_min_sigkill[:-1].strip()) - if mem_min_sigkill_mb is None: - print('Invalid mem_min_sigkill value, not float\nExit') - exit() - mem_min_sigkill_kb = mem_min_sigkill_mb * 1024 - if mem_min_sigkill_kb > mem_total: - print('mem_min_sigkill value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) - exit() - mem_min_sigkill_percent = mem_min_sigkill_kb / mem_total * 100 +# elif mem_min_sigterm.endswith('M'): +# mem_min_sigterm_mb = string_to_float_convert_test(mem_min_sigterm[:-1].strip()) +# if mem_min_sigterm_mb is None: +# print('Invalid mem_min_sigterm value, not float\nExit') +# exit() +# mem_min_sigterm_kb = mem_min_sigterm_mb * 1024 +# if mem_min_sigterm_kb > mem_total: +# print('mem_min_sigterm value can not be greater then MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) +# exit() +# mem_min_sigterm_percent = mem_min_sigterm_kb / mem_total * 100 - else: - print('Конфиг инвалид, для mem_min_sigkill неверно указаны единицы измерения\nExit') - exit() +# else: +# print('Invalid mem_min_sigterm units in config.\n Exit') +# exit() -else: - print('mem_min_sigkill not in config\nExit') - exit() +# else: +# print('mem_min_sigterm not in config\nExit') +# exit() +# if 'mem_min_sigkill' in config_dict: +# mem_min_sigkill = config_dict['mem_min_sigkill'] +# if mem_min_sigkill.endswith('%'): +# # truncate percent, so we have a number +# mem_min_sigkill_percent = mem_min_sigkill[:-1].strip() +# # then 'float test' +# mem_min_sigkill_percent = string_to_float_convert_test(mem_min_sigkill_percent) +# if mem_min_sigkill_percent is None: +# print('Invalid mem_min_sigkill value, not float\nExit') +# exit() +# # Final validation +# if mem_min_sigkill_percent < 0 or mem_min_sigkill_percent > 100: +# print('mem_min_sigkill, as a percentage, out of range [0; 100]\nExit') +# exit() + +# # mem_min_sigterm_percent is clean and valid float percentage. Can translate into Kb +# mem_min_sigkill_kb = mem_min_sigkill_percent / 100 * mem_total +# mem_min_sigkill_mb = round(mem_min_sigkill_kb / 1024) + +# elif mem_min_sigkill.endswith('M'): +# mem_min_sigkill_mb = string_to_float_convert_test(mem_min_sigkill[:-1].strip()) +# if mem_min_sigkill_mb is None: +# print('Invalid mem_min_sigkill value, not float\nExit') +# exit() +# mem_min_sigkill_kb = mem_min_sigkill_mb * 1024 +# if mem_min_sigkill_kb > mem_total: +# print('mem_min_sigkill value can not be greater then MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) +# exit() +# mem_min_sigkill_percent = mem_min_sigkill_kb / mem_total * 100 + +# else: +# print('Invalid mem_min_sigkill units in config\nExit') +# exit() + +# else: +# print('mem_min_sigkill not in config\nExit') +# exit() + + +mem_min_sigterm_percent = calculate_percent('mem_min_sigterm') +mem_min_sigkill_percent = calculate_percent('mem_min_sigkill') # НУЖНА ВАЛИДАЦИЯ НА МЕСТЕ! if 'swap_min_sigterm' in config_dict: @@ -812,84 +928,87 @@ else: exit() -if 'zram_max_sigterm' in config_dict: - zram_max_sigterm = config_dict['zram_max_sigterm'] +zram_max_sigterm_percent = calculate_percent('zram_max_sigterm') +zram_max_sigkill_percent = calculate_percent('zram_max_sigkill') - if zram_max_sigterm.endswith('%'): - # отбрасываем процент, получаем число - zram_max_sigterm_percent = zram_max_sigterm[:-1].strip() - # далее флоат тест - zram_max_sigterm_percent = string_to_float_convert_test(zram_max_sigterm_percent) - if zram_max_sigterm_percent is None: - print('Invalid zram_max_sigterm value, not float\nExit') - exit() - # окончательная валидация - if zram_max_sigterm_percent < 0 or zram_max_sigterm_percent > 100: - print('zram_max_sigterm, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit') - exit() +# if 'zram_max_sigterm' in config_dict: +# zram_max_sigterm = config_dict['zram_max_sigterm'] - # zram_max_sigterm_percent это теперь чистое валидное флоат число процентов, можно переводить в кб - zram_max_sigterm_kb = zram_max_sigterm_percent / 100 * mem_total - zram_max_sigterm_mb = round(zram_max_sigterm_kb / 1024) +# if zram_max_sigterm.endswith('%'): +# # отбрасываем процент, получаем число +# zram_max_sigterm_percent = zram_max_sigterm[:-1].strip() +# # далее флоат тест +# zram_max_sigterm_percent = string_to_float_convert_test(zram_max_sigterm_percent) +# if zram_max_sigterm_percent is None: +# print('Invalid zram_max_sigterm value, not float\nExit') +# exit() +# # окончательная валидация +# if zram_max_sigterm_percent < 0 or zram_max_sigterm_percent > 100: +# print('zram_max_sigterm, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit') +# exit() - elif zram_max_sigterm.endswith('M'): - zram_max_sigterm_mb = string_to_float_convert_test(zram_max_sigterm[:-1].strip()) - if zram_max_sigterm_mb is None: - print('Invalid zram_max_sigterm value, not float\nExit') - exit() - zram_max_sigterm_kb = zram_max_sigterm_mb * 1024 - if zram_max_sigterm_kb > mem_total: - print('zram_max_sigterm value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) - exit() - zram_max_sigterm_percent = zram_max_sigterm_kb / mem_total * 100 +# # zram_max_sigterm_percent это теперь чистое валидное флоат число процентов, можно переводить в кб +# zram_max_sigterm_kb = zram_max_sigterm_percent / 100 * mem_total +# zram_max_sigterm_mb = round(zram_max_sigterm_kb / 1024) - else: - print('Конфиг инвалид, для zram_max_sigterm неверно указаны единицы измерения\nExit') - exit() +# elif zram_max_sigterm.endswith('M'): +# zram_max_sigterm_mb = string_to_float_convert_test(zram_max_sigterm[:-1].strip()) +# if zram_max_sigterm_mb is None: +# print('Invalid zram_max_sigterm value, not float\nExit') +# exit() +# zram_max_sigterm_kb = zram_max_sigterm_mb * 1024 +# if zram_max_sigterm_kb > mem_total: +# print('zram_max_sigterm value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) +# exit() +# zram_max_sigterm_percent = zram_max_sigterm_kb / mem_total * 100 -else: - print('zram_max_sigterm not in config\nExit') - exit() +# else: +# print('Конфиг инвалид, для zram_max_sigterm неверно указаны единицы измерения\nExit') +# exit() + +# else: +# print('zram_max_sigterm not in config\nExit') +# exit() -if 'zram_max_sigkill' in config_dict: - zram_max_sigkill = config_dict['zram_max_sigkill'] +# if 'zram_max_sigkill' in config_dict: +# zram_max_sigkill = config_dict['zram_max_sigkill'] - if zram_max_sigkill.endswith('%'): - # отбрасываем процент, получаем число - zram_max_sigkill_percent = zram_max_sigkill[:-1].strip() - # далее флоат тест - zram_max_sigkill_percent = string_to_float_convert_test(zram_max_sigkill_percent) - if zram_max_sigkill_percent is None: - print('Invalid zram_max_sigkill value, not float\nExit') - exit() - # окончательная валидация - if zram_max_sigkill_percent < 0 or zram_max_sigkill_percent > 100: - print('zram_max_sigkill, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit') - exit() +# if zram_max_sigkill.endswith('%'): +# # отбрасываем процент, получаем число +# zram_max_sigkill_percent = zram_max_sigkill[:-1].strip() +# # далее флоат тест +# zram_max_sigkill_percent = string_to_float_convert_test(zram_max_sigkill_percent) +# if zram_max_sigkill_percent is None: +# print('Invalid zram_max_sigkill value, not float\nExit') +# exit() +# # окончательная валидация +# if zram_max_sigkill_percent < 0 or zram_max_sigkill_percent > 100: +# print('zram_max_sigkill, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit') +# exit() - # zram_max_sigkill_percent это теперь чистое валидное флоат число процентов, можно переводить в кб - zram_max_sigkill_kb = zram_max_sigkill_percent / 100 * mem_total - zram_max_sigkill_mb = round(zram_max_sigkill_kb / 1024) +# # zram_max_sigkill_percent это теперь чистое валидное флоат число процентов, можно переводить в кб +# zram_max_sigkill_kb = zram_max_sigkill_percent / 100 * mem_total +# zram_max_sigkill_mb = round(zram_max_sigkill_kb / 1024) - elif zram_max_sigkill.endswith('M'): - zram_max_sigkill_mb = string_to_float_convert_test(zram_max_sigkill[:-1].strip()) - if zram_max_sigkill_mb is None: - print('Invalid zram_max_sigkill value, not float\nExit') - exit() - zram_max_sigkill_kb = zram_max_sigkill_mb * 1024 - if zram_max_sigkill_kb > mem_total: - print('zram_max_sigkill value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) - exit() - zram_max_sigkill_percent = zram_max_sigkill_kb / mem_total * 100 +# elif zram_max_sigkill.endswith('M'): +# zram_max_sigkill_mb = string_to_float_convert_test(zram_max_sigkill[:-1].strip()) +# if zram_max_sigkill_mb is None: +# print('Invalid zram_max_sigkill value, not float\nExit') +# exit() +# zram_max_sigkill_kb = zram_max_sigkill_mb * 1024 +# if zram_max_sigkill_kb > mem_total: +# print('zram_max_sigkill value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) +# exit() +# zram_max_sigkill_percent = zram_max_sigkill_kb / mem_total * 100 - else: - print('Конфиг инвалид, для zram_max_sigkill неверно указаны единицы измерения\nExit') - exit() +# else: +# print('Конфиг инвалид, для zram_max_sigkill неверно указаны единицы измерения\nExit') +# exit() -else: - print('zram_max_sigkill not in config\nExit') - exit() +# else: +# print('zram_max_sigkill not in config\nExit') +# exit() if 'min_delay_after_sigterm' in config_dict: @@ -951,7 +1070,6 @@ else: exit() - regex_matching = conf_parse_bool('regex_matching') @@ -987,13 +1105,11 @@ else: exit() - gui_low_memory_warnings = conf_parse_bool('gui_low_memory_warnings') gui_notifications = conf_parse_bool('gui_notifications') - if 'min_time_between_warnings' in config_dict: min_time_between_warnings = string_to_float_convert_test( config_dict['min_time_between_warnings']) @@ -1008,45 +1124,46 @@ else: exit() -if 'mem_min_warnings' in config_dict: - mem_min_warnings = config_dict['mem_min_warnings'] +mem_min_warnings_percent = calculate_percent('mem_min_warnings') - if mem_min_warnings.endswith('%'): - # отбрасываем процент, получаем число - mem_min_warnings_percent = mem_min_warnings[:-1].strip() - # далее флоат тест - mem_min_warnings_percent = string_to_float_convert_test(mem_min_warnings_percent) - if mem_min_warnings_percent is None: - print('Invalid mem_min_warnings value, not float\nExit') - exit() - # окончательная валидация - if mem_min_warnings_percent < 0 or mem_min_warnings_percent > 100: - print('mem_min_warnings, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit') - exit() +# if 'mem_min_warnings' in config_dict: +# mem_min_warnings = config_dict['mem_min_warnings'] - # mem_min_warnings_percent это теперь чистое валидное флоат число процентов, можно переводить в кб - mem_min_warnings_kb = mem_min_warnings_percent / 100 * mem_total - mem_min_warnings_mb = round(mem_min_warnings_kb / 1024) +# if mem_min_warnings.endswith('%'): +# # отбрасываем процент, получаем число +# mem_min_warnings_percent = mem_min_warnings[:-1].strip() +# # далее флоат тест +# mem_min_warnings_percent = string_to_float_convert_test(mem_min_warnings_percent) +# if mem_min_warnings_percent is None: +# print('Invalid mem_min_warnings value, not float\nExit') +# exit() +# # окончательная валидация +# if mem_min_warnings_percent < 0 or mem_min_warnings_percent > 100: +# print('mem_min_warnings, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit') +# exit() - elif mem_min_warnings.endswith('M'): - mem_min_warnings_mb = string_to_float_convert_test(mem_min_warnings[:-1].strip()) - if mem_min_warnings_mb is None: - print('Invalid mem_min_warnings value, not float\nExit') - exit() - mem_min_warnings_kb = mem_min_warnings_mb * 1024 - if mem_min_warnings_kb > mem_total: - print('mem_min_warnings value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) - exit() - mem_min_warnings_percent = mem_min_warnings_kb / mem_total * 100 +# # mem_min_warnings_percent это теперь чистое валидное флоат число процентов, можно переводить в кб +# mem_min_warnings_kb = mem_min_warnings_percent / 100 * mem_total +# mem_min_warnings_mb = round(mem_min_warnings_kb / 1024) - else: - print('Конфиг инвалид, для mem_min_warnings неверно указаны единицы измерения\nExit') - exit() +# elif mem_min_warnings.endswith('M'): +# mem_min_warnings_mb = string_to_float_convert_test(mem_min_warnings[:-1].strip()) +# if mem_min_warnings_mb is None: +# print('Invalid mem_min_warnings value, not float\nExit') +# exit() +# mem_min_warnings_kb = mem_min_warnings_mb * 1024 +# if mem_min_warnings_kb > mem_total: +# print('mem_min_warnings value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) +# exit() +# mem_min_warnings_percent = mem_min_warnings_kb / mem_total * 100 -else: - print('mem_min_warnings not in config\nExit') - exit() +# else: +# print('Конфиг инвалид, для mem_min_warnings неверно указаны единицы измерения\nExit') +# exit() +# else: +# print('mem_min_warnings not in config\nExit') +# exit() # НА МЕСТЕ!!! @@ -1057,45 +1174,46 @@ else: exit() +zram_max_warnings_percent = calculate_percent('zram_max_warnings..') -if 'zram_max_warnings' in config_dict: - zram_max_warnings = config_dict['zram_max_warnings'] +# if 'zram_max_warnings' in config_dict: +# zram_max_warnings = config_dict['zram_max_warnings'] - if zram_max_warnings.endswith('%'): - # отбрасываем процент, получаем число - zram_max_warnings_percent = zram_max_warnings[:-1].strip() - # далее флоат тест - zram_max_warnings_percent = string_to_float_convert_test(zram_max_warnings_percent) - if zram_max_warnings_percent is None: - print('Invalid zram_max_warnings value, not float\nExit') - exit() - # окончательная валидация - if zram_max_warnings_percent < 0 or zram_max_warnings_percent > 100: - print('zram_max_warnings, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit') - exit() +# if zram_max_warnings.endswith('%'): +# # отбрасываем процент, получаем число +# zram_max_warnings_percent = zram_max_warnings[:-1].strip() +# # далее флоат тест +# zram_max_warnings_percent = string_to_float_convert_test(zram_max_warnings_percent) +# if zram_max_warnings_percent is None: +# print('Invalid zram_max_warnings value, not float\nExit') +# exit() +# # окончательная валидация +# if zram_max_warnings_percent < 0 or zram_max_warnings_percent > 100: +# print('zram_max_warnings, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit') +# exit() - # zram_max_warnings_percent это теперь чистое валидное флоат число процентов, можно переводить в кб - zram_max_warnings_kb = zram_max_warnings_percent / 100 * mem_total - zram_max_warnings_mb = round(zram_max_warnings_kb / 1024) +# # zram_max_warnings_percent это теперь чистое валидное флоат число процентов, можно переводить в кб +# zram_max_warnings_kb = zram_max_warnings_percent / 100 * mem_total +# zram_max_warnings_mb = round(zram_max_warnings_kb / 1024) - elif zram_max_warnings.endswith('M'): - zram_max_warnings_mb = string_to_float_convert_test(zram_max_warnings[:-1].strip()) - if zram_max_warnings_mb is None: - print('Invalid zram_max_warnings value, not float\nExit') - exit() - zram_max_warnings_kb = zram_max_warnings_mb * 1024 - if zram_max_warnings_kb > mem_total: - print('zram_max_warnings value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) - exit() - zram_max_warnings_percent = zram_max_warnings_kb / mem_total * 100 +# elif zram_max_warnings.endswith('M'): +# zram_max_warnings_mb = string_to_float_convert_test(zram_max_warnings[:-1].strip()) +# if zram_max_warnings_mb is None: +# print('Invalid zram_max_warnings value, not float\nExit') +# exit() +# zram_max_warnings_kb = zram_max_warnings_mb * 1024 +# if zram_max_warnings_kb > mem_total: +# print('zram_max_warnings value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024))) +# exit() +# zram_max_warnings_percent = zram_max_warnings_kb / mem_total * 100 - else: - print('Конфиг инвалид, для zram_max_warnings неверно указаны единицы измерения\nExit') - exit() +# else: +# print('Конфиг инвалид, для zram_max_warnings неверно указаны единицы измерения\nExit') +# exit() -else: - print('zram_max_warnings not in config\nExit') - exit() +# else: +# print('zram_max_warnings not in config\nExit') +# exit() execute_the_command = conf_parse_bool('execute_the_command') @@ -1151,7 +1269,7 @@ else: ########################################################################## -# self-defense +# self-defense # повышаем приоритет try: @@ -1189,7 +1307,6 @@ self_uid = os.geteuid() self_pid = os.getpid() - if self_uid == 0: root = True decrease_res = 'OK' @@ -1198,7 +1315,6 @@ else: decrease_res = 'Impossible' - if root and realtime_ionice: os.system('ionice -c 1 -n {} -p {}'.format( realtime_ionice_classdata, self_pid)) @@ -1209,7 +1325,6 @@ if root and realtime_ionice: if print_config: - print('\n1. Memory levels to respond to as an OOM threat\n[displaying these options need fix]\n') print('mem_min_sigterm: {} MiB, {} %'.format( @@ -1225,13 +1340,11 @@ if print_config: print('zram_max_sigkill: {} MiB, {} %'.format( round(zram_max_sigkill_mb), round(zram_max_sigkill_percent, 1))) - print('\n2. The frequency of checking the level of available memory (and CPU usage)\n') print('rate_mem: {}'.format(rate_mem)) print('rate_swap: {}'.format(rate_swap)) print('rate_zram: {}'.format(rate_zram)) - print('\n3. The prevention of killing innocent victims\n') print('min_delay_after_sigterm: {}'.format(min_delay_after_sigterm)) print('min_delay_after_sigkill: {}'.format(min_delay_after_sigkill)) @@ -1244,7 +1357,6 @@ if print_config: if decrease_oom_score_adj: print('oom_score_adj_max: {}'.format(oom_score_adj_max)) - print('\n4. Impact on the badness of processes via matching their names\nwith regular expressions\n') print('regex_matching: {}'.format(regex_matching)) if regex_matching: @@ -1253,7 +1365,6 @@ if print_config: print('avoid_regex: {}'.format(avoid_regex)) print('avoid_factor: {}'.format(avoid_factor)) - print('\n5. The execution of a specific command instead of sending the\nSIGTERM signal\n') print('execute_the_command: {}'.format(execute_the_command)) if execute_the_command: @@ -1261,7 +1372,6 @@ if print_config: for key in etc_dict: print('{} {}'.format(key.ljust(15), etc_dict[key])) - print('\n6. GUI notifications:\n- OOM prevention results and\n- low memory warnings\n') print('gui_notifications: {}'.format(gui_notifications)) @@ -1277,7 +1387,6 @@ if print_config: print('zram_max_warnings: {} MiB, {} %'.format( round(zram_max_warnings_mb), round(zram_max_warnings_percent, 1))) - print('\n7. Preventing the slowing down of the program\n[displaying these options need fix]\n') print('mlockall: {} ({})'.format(mlockall, mla_res)) print('niceness: {} ({})'.format( @@ -1308,7 +1417,7 @@ mem_len = len(str(round(mem_total / 1024.0))) if gui_notifications or gui_low_memory_warnings: from subprocess import Popen, PIPE notify_sig_dict = {signal.SIGKILL: 'Killing', - signal.SIGTERM: 'Terminating'} + signal.SIGTERM: 'Terminating'} if regex_matching: @@ -1328,11 +1437,6 @@ print('Monitoring started!') ########################################################################## - - - - - while True: # find mem_available, swap_total, swap_free @@ -1348,8 +1452,6 @@ while True: swap_free = int(line.split(':')[1].strip(' kB\n')) break - - # if swap_min_sigkill is set in percent if swap_kill_is_percent: swap_min_sigkill_kb = swap_total * swap_min_sigkill_percent / 100.0 @@ -1360,7 +1462,6 @@ while True: if swap_warn_is_percent: swap_min_warnings_kb = swap_total * swap_min_warnings_percent / 100.0 - # find MemUsedZram disksize_sum = 0 mem_used_total_sum = 0 @@ -1373,7 +1474,6 @@ while True: mem_used_total_sum + disksize_sum * zram_disksize_factor ) / 1024.0 - if print_mem_check_results: # для рассчета ширины столбца свопа @@ -1393,15 +1493,14 @@ while True: just_percent_swap(swap_free / (swap_total + 0.1)))) else: - print('MemAvail: {} M, {} % | SwapFree: {} M, {} % | Mem' \ - 'UsedZram: {} M, {} %'.format( - human(mem_available, mem_len), - just_percent_mem(mem_available / mem_total), - human(swap_free, swap_len), - just_percent_swap(swap_free / (swap_total + 0.1)), - human(mem_used_zram, mem_len), - just_percent_mem(mem_used_zram / mem_total))) - + print('MemAvail: {} M, {} % | SwapFree: {} M, {} % | Mem' + 'UsedZram: {} M, {} %'.format( + human(mem_available, mem_len), + just_percent_mem(mem_available / mem_total), + human(swap_free, swap_len), + just_percent_swap(swap_free / (swap_total + 0.1)), + human(mem_used_zram, mem_len), + just_percent_mem(mem_used_zram / mem_total))) # если swap_min_sigkill задан в абсолютной величине и Swap_total = 0 if swap_total > swap_min_sigkill_kb: @@ -1416,9 +1515,6 @@ while True: # СТОИТ ПЕЧАТАТЬ СВОП ТОЛЬКО ПРИ SwapTotal > 0 swap_sigterm_pc = '-' - - - # проверка превышения порогов # порог превышен - пытаемся предотвратить OOM # пороги не превышены - спим @@ -1429,16 +1525,16 @@ while True: mem_info = 'Low memory; corrective action required!\n MemAvailable [{} MiB, {} %] <= mem_min_sigkill [{} MiB, {} %]\n Swa' \ 'pFree [{} MiB, {} %] <= swap_min_sigkill [{} MiB, {} %]'.format( - kib_to_mib(mem_available), - percent(mem_available / mem_total), + kib_to_mib(mem_available), + percent(mem_available / mem_total), - kib_to_mib(mem_min_sigkill_kb), - percent(mem_min_sigkill_kb / mem_total), + kib_to_mib(mem_min_sigkill_kb), + percent(mem_min_sigkill_kb / mem_total), - kib_to_mib(swap_free), - percent(swap_free / (swap_total + 0.1)), + kib_to_mib(swap_free), + percent(swap_free / (swap_total + 0.1)), - kib_to_mib(swap_min_sigkill_kb), + kib_to_mib(swap_min_sigkill_kb), swap_sigkill_pc) find_victim_and_send_signal(signal.SIGKILL) @@ -1457,25 +1553,25 @@ while True: # MEM SWAP TERM elif mem_available <= mem_min_sigterm_kb and swap_free <= swap_min_sigterm_kb: - + time0 = time() mem_info = 'Low memory; corrective action required!\n MemAvailable [{} MiB, {} %] <= mem_min_sigterm [{} MiB, {} %]\n Sw' \ 'apFree [{} MiB, {} %] <= swap_min_sigterm [{} MiB, {} %]'.format( kib_to_mib(mem_available), percent(mem_available / mem_total), - - + + kib_to_mib(mem_min_sigterm_kb), #percent(mem_min_sigterm_kb / mem_total), - + # ОКРУГЛЯТЬ НА МЕСТЕ ВЫШЕ round(mem_min_sigterm_percent, 1), - + kib_to_mib(swap_free), percent(swap_free / (swap_total + 0.1)), - - + + kib_to_mib(swap_min_sigterm_kb), swap_sigterm_pc) @@ -1487,9 +1583,9 @@ while True: mem_info = 'Low memory; corrective action required!\n MemUsedZram [{} MiB, {} %] >= zram_max_sigter' \ 'm [{} M, {} %]'.format( - kib_to_mib(mem_used_zram), - percent(mem_used_zram / mem_total), - kib_to_mib(zram_max_sigterm_kb), + kib_to_mib(mem_used_zram), + percent(mem_used_zram / mem_total), + kib_to_mib(zram_max_sigterm_kb), percent(zram_max_sigterm_kb / mem_total)) find_victim_and_send_signal(signal.SIGTERM) @@ -1506,10 +1602,12 @@ while True: warn_timer = 0 sleep_after_check_mem() - # SLEEP BETWEEN MEM CHECKS else: stdout.flush() sleep_after_check_mem() +_check_mem() +em() +_check_mem()