diff --git a/nohang b/nohang index d54f89e..65f5629 100755 --- a/nohang +++ b/nohang @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""A daemon that prevents OOM in linux systems.""" +"""A daemon that prevents OOM in Linux systems.""" import os import signal from operator import itemgetter @@ -22,21 +22,9 @@ conf_err_mess = '\nSet up the path to the valid conf' \ 'ig file with -c/--config option!\nExit' -# означает, что при задани zram disksize = 10000M доступная память -# уменьшится на 42M -# найден экспериментально, требует уточнения с разными ядрами и архитектурами -# на небольших дисксайзах (до гигабайта) может быть больше, до 0.0045 -# создатель модуля zram утверждает, что zram_disksize_factor доожен быть 0.001 -# ("zram uses about 0.1% of the size of the disk" -# - https://www.kernel.org/doc/Documentation/blockdev/zram.txt), -# но это утверждение противоречит опытным данным - -# zram_disksize_factor = deltaMemAvailavle / disksize -# found experimentally -zram_disksize_factor = 0.0042 - ########################################################################## + # function definition section @@ -137,7 +125,7 @@ def conf_parse_bool(param): def func_decrease_oom_score_adj(oom_score_adj_max): """ - Pls, put description here... + Stupid function, must be removed or remaked """ for i in os.listdir('/proc'): if i.isdigit() is not True: @@ -185,9 +173,8 @@ def just_percent_swap(num): return str(round(num * 100, 1)).rjust(5, ' ') -# KiB to MiB, right alignment def human(num, lenth): - """Convert Kib values to Mib values with right alignment""" + """Convert KiB values to MiB values with right alignment""" return str(round(num / 1024)).rjust(lenth, ' ') @@ -238,8 +225,6 @@ 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() @@ -268,8 +253,7 @@ def send_notify_warn(): '--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)]) + Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)]) def send_notify(signal, name, pid): @@ -294,7 +278,8 @@ def send_notify(signal, name, pid): '{}'.format(title), '{}'.format(body)]) else: # send notification to user that runs this nohang - Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)]) + Popen(['notify-send', '--icon=dialog-warning', + '{}'.format(title), '{}'.format(body)]) def send_notify_etc(pid, name, command): @@ -341,9 +326,7 @@ def sleep_after_send_signal(signal): def find_victim_and_send_signal(signal): """ - Please describe this. - - thanks + Find victim with highest badness and send SIGTERM/SIGKILL """ if decrease_oom_score_adj and root: func_decrease_oom_score_adj(oom_score_adj_max) @@ -442,27 +425,34 @@ def find_victim_and_send_signal(signal): try: os.kill(int(pid), signal) response_time = time() - time0 - send_result = 'OK; response time: {} ms'.format(round(response_time * 1000)) + send_result = 'OK; response time: {} ms'.format( + round(response_time * 1000)) if gui_notifications: send_notify(signal, name, pid) except FileNotFoundError: response_time = time() - time0 - send_result = 'no such process; response time: {} ms'.format(round(response_time * 1000)) + send_result = 'no such process; response time: {} ms'.format( + round(response_time * 1000)) except ProcessLookupError: response_time = time() - time0 - send_result = 'no such process; response time: {} ms'.format(round(response_time * 1000)) + 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) + preventing_oom_message = ' Finding the process with the highes' \ + 't badness\n Victim is {}, pid: {}, badness: {}, VmRS' \ + 'S: {} 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) else: response_time = time() - time0 - victim_badness_is_too_small = ' victim badness {} < min_badness {}; nothing to do; response time: {} ms'.format(victim_badness, min_badness, round(response_time * 1000)) + victim_badness_is_too_small = ' victim badness {} < min_badness {}; nothing to do; response time: {} ms'.format( + victim_badness, min_badness, round(response_time * 1000)) print(victim_badness_is_too_small) @@ -487,8 +477,13 @@ def sleep_after_check_mem(): try: if print_sleep_periods: - print('sleep', round(t, 2), ' (t_mem={}, t_swap={}, t_zram={})'.format( - round(t_mem, 2), round(t_swap, 2), round(t_zram, 2))) + print( + 'sleep', round( + t, 2), ' (t_mem={}, t_swap={}, t_zram={})'.format( + round( + t_mem, 2), round( + t_swap, 2), round( + t_zram, 2))) sleep(t) except KeyboardInterrupt: exit() @@ -544,9 +539,68 @@ def fattest(): return (name, pid) +def calculate_percent(arg_key): + """ + parse conf dict + Calculate mem_min_KEY_percent. + + Try use this one) + arg_key: str key for config_dict + returns int mem_min_percent or NoneType if got some error + """ + + if arg_key in config_dict: + mem_min = config_dict[arg_key] + + 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_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('{} not in config\nExit'.format(arg_key)) + mem_min_percent = None + + return mem_min_kb, mem_min_mb, mem_min_percent + + ########################################################################## -# поиск позиций и mem_total + +# find mem_total +# find positions of SwapFree and SwapTotal in /proc/meminfo with open('/proc/meminfo') as file: mem_list = file.readlines() @@ -556,7 +610,7 @@ for s in mem_list: mem_list_names.append(s.split(':')[0]) if mem_list_names[2] != 'MemAvailable': - print('Your Linux kernel is too old, Linux 3.14+ requie\nExit') + print('Your Linux kernel is too old, Linux 3.14+ requied\nExit') exit() swap_total_index = mem_list_names.index('SwapTotal') @@ -564,10 +618,11 @@ swap_free_index = swap_total_index + 1 mem_total = int(mem_list[0].split(':')[1].strip(' kB\n')) +# 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() -# 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]) @@ -575,8 +630,10 @@ for s in status_list: vm_rss_index = status_names.index('VmRSS') vm_swap_index = status_names.index('VmSwap') + ########################################################################## + # Configurations # Cmd argparse @@ -617,8 +674,10 @@ else: print('The path to the config:', config) + ########################################################################## + # parsing the config with obtaining the parameters dictionary # conf_parameters_dict @@ -630,7 +689,8 @@ try: # dictionary with config options config_dict = dict() - # dictionary with names and commands for the parameter execute_the_command + # dictionary with names and commands for the parameter + # execute_the_command etc_dict = dict() for line in f: @@ -651,7 +711,8 @@ try: etc_name = a[0].strip() etc_command = a[1].strip() if len(etc_name) > 15: - print('Invalid config, the length of the process name must not exceed 15 characters\nExit') + print( + 'Invalid config, the length of the process name must not exceed 15 characters\nExit') exit() etc_dict[etc_name] = etc_command @@ -668,23 +729,42 @@ except IndexError: print('IndexError', conf_err_mess) exit() + ########################################################################## + # extracting parameters from the dictionary # check for all necessary parameters # validation of all parameters - print_config = conf_parse_bool('print_config') - - print_mem_check_results = conf_parse_bool('print_mem_check_results') - - print_sleep_periods = conf_parse_bool('print_sleep_periods') - - realtime_ionice = conf_parse_bool('realtime_ionice') +mlockall = conf_parse_bool('mlockall') +gui_low_memory_warnings = conf_parse_bool('gui_low_memory_warnings') +gui_notifications = conf_parse_bool('gui_notifications') +decrease_oom_score_adj = conf_parse_bool('decrease_oom_score_adj') +regex_matching = conf_parse_bool('regex_matching') +execute_the_command = conf_parse_bool('execute_the_command') + +prefer_regex = conf_parse_string('prefer_regex') +avoid_regex = conf_parse_string('avoid_regex') + +mem_min_sigterm_kb, mem_min_sigterm_mb, mem_min_sigterm_percent = calculate_percent( + 'mem_min_sigterm') +mem_min_sigkill_kb, mem_min_sigkill_mb, mem_min_sigkill_percent = calculate_percent( + 'mem_min_sigkill') + +zram_max_sigterm_kb, zram_max_sigterm_mb, zram_max_sigterm_percent = calculate_percent( + 'zram_max_sigterm') +zram_max_sigkill_kb, zram_max_sigkill_mb, zram_max_sigkill_percent = calculate_percent( + 'zram_max_sigkill') + +mem_min_warnings_kb, mem_min_warnings_mb, mem_min_warnings_percent = calculate_percent( + 'mem_min_warnings') +zram_max_warnings_kb, zram_max_warnings_mb, zram_max_warnings_percent = calculate_percent( + 'zram_max_warnings') if 'realtime_ionice_classdata' in config_dict: @@ -706,9 +786,6 @@ else: exit() -mlockall = conf_parse_bool('mlockall') - - if 'niceness' in config_dict: niceness = string_to_int_convert_test(config_dict['niceness']) if niceness is None: @@ -775,143 +852,6 @@ else: exit() -def calculate_percent(arg_key): - """ - Calculate mem_min_KEY_percent. - - 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 - - if arg_key in config_dict: - mem_min = config_dict[arg_key] - - 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_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('{} not in config\nExit'.format(arg_key)) - mem_min_percent = None - - return mem_min_kb, mem_min_mb, mem_min_percent - - -# if 'mem_min_sigterm' in config_dict: -# mem_min_sigterm = config_dict['mem_min_sigterm'] - -# 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 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_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('Invalid mem_min_sigterm units in config.\n Exit') -# 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_kb, mem_min_sigterm_mb, mem_min_sigterm_percent = calculate_percent('mem_min_sigterm') -mem_min_sigkill_kb, mem_min_sigkill_mb, mem_min_sigkill_percent = calculate_percent('mem_min_sigkill') - # НУЖНА ВАЛИДАЦИЯ НА МЕСТЕ! if 'swap_min_sigterm' in config_dict: swap_min_sigterm = config_dict['swap_min_sigterm'] @@ -928,89 +868,6 @@ else: exit() -zram_max_sigterm_kb, zram_max_sigterm_mb, zram_max_sigterm_percent = calculate_percent('zram_max_sigterm') -zram_max_sigkill_kb, zram_max_sigkill_mb, zram_max_sigkill_percent = calculate_percent('zram_max_sigkill') - -# if 'zram_max_sigterm' in config_dict: -# zram_max_sigterm = config_dict['zram_max_sigterm'] - -# 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() - -# # 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) - -# 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 неверно указаны единицы измерения\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.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) - -# 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 not in config\nExit') -# exit() - - if 'min_delay_after_sigterm' in config_dict: min_delay_after_sigterm = string_to_float_convert_test( config_dict['min_delay_after_sigterm']) @@ -1053,9 +910,6 @@ else: exit() -decrease_oom_score_adj = conf_parse_bool('decrease_oom_score_adj') - - if 'oom_score_adj_max' in config_dict: oom_score_adj_max = string_to_int_convert_test( config_dict['oom_score_adj_max']) @@ -1070,12 +924,6 @@ else: exit() -regex_matching = conf_parse_bool('regex_matching') - - -prefer_regex = conf_parse_string('prefer_regex') - - if 'prefer_factor' in config_dict: prefer_factor = string_to_float_convert_test(config_dict['prefer_factor']) if prefer_factor is None: @@ -1089,9 +937,6 @@ else: exit() -avoid_regex = conf_parse_string('avoid_regex') - - if 'avoid_factor' in config_dict: avoid_factor = string_to_float_convert_test(config_dict['avoid_factor']) if avoid_factor is None: @@ -1105,11 +950,6 @@ 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']) @@ -1124,48 +964,6 @@ else: exit() -mem_min_warnings_kb, mem_min_warnings_mb, mem_min_warnings_percent = calculate_percent('mem_min_warnings') - -# if 'mem_min_warnings' in config_dict: -# mem_min_warnings = config_dict['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() - -# # 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) - -# 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 неверно указаны единицы измерения\nExit') -# exit() - -# else: -# print('mem_min_warnings not in config\nExit') -# exit() - - # НА МЕСТЕ!!! if 'swap_min_warnings' in config_dict: swap_min_warnings = config_dict['swap_min_warnings'] @@ -1174,60 +972,16 @@ else: exit() -zram_max_warnings_kb, zram_max_warnings_mb, 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.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) - -# 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 not in config\nExit') -# exit() - - -execute_the_command = conf_parse_bool('execute_the_command') - - ########################################################################## + # Get Kibibytes levels -# Returns Kilobytes value if absolute value was set in config, +# Returns Kibibytes value if absolute value was set in config, # or tuple with percentage def sig_level_to_kb_swap(string): - """Returns Kilobytes value if abs val was set in config, or tuple with %""" + """Returns Kibibytes value if abs val was set in config, or tuple with %""" if string.endswith('%'): return float(string[:-1].strip()), True elif string.endswith('M'): @@ -1271,6 +1025,9 @@ else: # self-defense + +# возожно стоит убрать поддержку mlockall и ionice + # Increase priority try: os.nice(niceness) @@ -1285,11 +1042,9 @@ try: file.write('{}\n'.format(oom_score_adj)) oom_score_adj_result = 'OK' except PermissionError: - pass oom_score_adj_result = 'Fail' except OSError: oom_score_adj_result = 'Fail' - pass # Deny process swapping if mlockall: @@ -1324,7 +1079,8 @@ 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( + '\n1. Memory levels to respond to as an OOM threat\n[displaying these options need fix]\n') print('mem_min_sigterm: {} MiB, {} %'.format( round(mem_min_sigterm_mb), round(mem_min_sigterm_percent, 1))) @@ -1386,7 +1142,8 @@ 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( + '\n7. Preventing the slowing down of the program\n[displaying these options need fix]\n') print('mlockall: {} ({})'.format(mlockall, mla_res)) print('niceness: {} ({})'.format( niceness, niceness_result @@ -1433,6 +1190,9 @@ warn_timer = 0 print('Monitoring started!') + + + ########################################################################## @@ -1461,6 +1221,7 @@ 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 @@ -1469,10 +1230,24 @@ while True: stat = zram_stat(dev) disksize_sum += int(stat[0]) mem_used_total_sum += int(stat[1]) + + # Означает, что при задани zram disksize = 10000M доступная память + # уменьшится на 42 MiB. + # Найден экспериментально, требует уточнения с разными ядрами и архитектурами. + # На небольших дисксайзах (до гигабайта) может быть больше, до 0.0045. + # Создатель модуля zram утверждает, что zram_disksize_factor доожен быть 0.001 + # ("zram uses about 0.1% of the size of the disk" + # - https://www.kernel.org/doc/Documentation/blockdev/zram.txt), + # но это утверждение противоречит опытным данным. + # zram_disksize_factor = deltaMemAvailavle / disksize + # found experimentally + zram_disksize_factor = 0.0042 + mem_used_zram = ( mem_used_total_sum + disksize_sum * zram_disksize_factor ) / 1024.0 + if print_mem_check_results: # Calculate 'swap-column' width @@ -1512,6 +1287,7 @@ while True: else: # СТОИТ ПЕЧАТАТЬ СВОП ТОЛЬКО ПРИ SwapTotal > 0 + # нет, печатать так: SwapTotal = 0 KiB, ignore swapspace swap_sigterm_pc = '-' # Limits overdrafting checks @@ -1592,7 +1368,8 @@ while True: # LOW MEMORY WARNINGS elif gui_low_memory_warnings: - if mem_available <= mem_min_warnings_kb and swap_free <= swap_min_warnings_kb + 0.1 or mem_used_zram >= zram_max_warnings_kb: + if mem_available <= mem_min_warnings_kb and swap_free <= swap_min_warnings_kb + \ + 0.1 or mem_used_zram >= zram_max_warnings_kb: warn_time_delta = time() - warn_time_now warn_time_now = time() warn_timer += warn_time_delta @@ -1603,7 +1380,5 @@ while True: # SLEEP BETWEEN MEM CHECKS else: - stdout.flush() - sleep_after_check_mem()