diff --git a/nohang b/nohang index f868611..607582f 100755 --- a/nohang +++ b/nohang @@ -40,27 +40,11 @@ HR = '~' * 79 print_total_stat = True - ########################################################################## # define functions - - - -def zenity(): - # test - os.system('''sudo -u user DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus zenity --checklist --timeout=10 --text="\n Mem Available: 10% (300 MiB). \n\n Select a process to be terminated:\n" --ok-label "Terminate" --cancel-label "Do nothing" --separator=" " --width=9999 --height=9999 --list --title="Low memory!" --column "" --column="Pid" --column="Name" --column="VmRSS" 9923 9923 Python3 "800 MiB" 2938 2938 tail "400 MiB" 3938 3938 chromium "300 MiB"''') - -# zenity() - - - - - - - def update_stat_dict_and_print(key): if key not in stat_dict: @@ -83,7 +67,6 @@ def update_stat_dict_and_print(key): print(stats_msg) - def psi_mem_some_avg_total(): if psi_support: return float(rline1(psi_path).rpartition('=')[2]) @@ -510,11 +493,6 @@ def find_victim_and_send_signal(signal): if victim_badness >= min_badness: - - - - - # Try to send signal to found victim # Get VmRSS and VmSwap and cmdline of victim process @@ -566,12 +544,14 @@ def find_victim_and_send_signal(signal): except FileNotFoundError: print(mem_info) print('The victim died in the search process: FileNotFoundError') - update_stat_dict_and_print('The victim died in the search process: FileNotFoundError') + update_stat_dict_and_print( + 'The victim died in the search process: FileNotFoundError') return None except ProcessLookupError: print(mem_info) print('The victim died in the search process: ProcessLookupError') - update_stat_dict_and_print('The victim died in the search process: ProcessLookupError') + update_stat_dict_and_print( + 'The victim died in the search process: ProcessLookupError') return None except UnicodeDecodeError: @@ -585,7 +565,8 @@ def find_victim_and_send_signal(signal): uid = f_list[i].split('\t')[2] if i is vm_size_index: - vm_size = kib_to_mib(int(f_list[i].split('\t')[1][:-3])) + vm_size = kib_to_mib( + int(f_list[i].split('\t')[1][:-3])) if i is vm_rss_index: vm_rss = kib_to_mib(int(f_list[i].split('\t')[1][:-3])) @@ -605,8 +586,8 @@ def find_victim_and_send_signal(signal): 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])) - + vm_swap = kib_to_mib( + int(f_list[i].split('\t')[1][:-3])) with open('/proc/' + pid + '/cmdline') as file: cmdline = file.readlines()[0].replace('\x00', ' ') @@ -617,15 +598,16 @@ def find_victim_and_send_signal(signal): except IndexError: print(mem_info) print('The victim died in the search process: IndexError') - update_stat_dict_and_print('The victim died in the search process: IndexError') + update_stat_dict_and_print( + 'The victim died in the search process: IndexError') return None except ValueError: print(mem_info) print('The victim died in the search process: ValueError') - update_stat_dict_and_print('The victim died in the search process: ValueError') + update_stat_dict_and_print( + 'The victim died in the search process: ValueError') return None - len_vm = len(str(vm_size)) if detailed_rss: @@ -679,16 +661,6 @@ def find_victim_and_send_signal(signal): str(vm_swap).rjust(len_vm), cmdline) - - - - - - - - - - if execute_the_command and signal is SIGTERM and name in etc_dict: command = etc_dict[name] exit_status = os.system(etc_dict[name].replace( @@ -719,22 +691,16 @@ def find_victim_and_send_signal(signal): name, command.replace('$PID', pid).replace('$NAME', pid_to_name(pid))) - - - - else: try: - - t0 = time() + m = check_mem_and_swap() ma = round(int(m[0]) / 1024.0) sf = round(int(m[2]) / 1024.0) - print('\nMemory status before sending a signal:\nMemAv: {} MiB, SwFree: {} MiB'.format(ma, sf)) - print(time() - t0) - - + print('\nMemory status before sending a signal:\nMemA' + 'v: {} MiB, SwFree: {} MiB'.format(ma, sf)) + os.kill(int(pid), signal) response_time = time() - time0 send_result = '\033[32mOK\033[0m; response time: {} ms'.format( @@ -748,10 +714,6 @@ def find_victim_and_send_signal(signal): key = 'Send \033[35m{}\033[0m to \033[35m{}\033[0m'.format( sig_dict[signal], name) - - # zenity() - - if gui_notifications: send_notify(signal, name, pid) @@ -766,15 +728,11 @@ def find_victim_and_send_signal(signal): round(response_time * 1000)) key = 'The victim died in the search process: ProcessLookupError' - print(mem_info) print(preventing_oom_message) update_stat_dict_and_print(key) - - - else: response_time = time() - time0 @@ -791,11 +749,9 @@ def find_victim_and_send_signal(signal): key = 'victim badness < min_badness' update_stat_dict_and_print(key) - sleep_after_send_signal(signal) - def sleep_after_check_mem(): """Specify sleep times depends on rates and avialable memory.""" @@ -955,6 +911,8 @@ cd = os.getcwd() config = '/etc/nohang/nohang.conf' +# config = 'nohang.conf' + print('Config:', config) @@ -1121,7 +1079,6 @@ else: exit() -# НУЖНА ВАЛИДАЦИЯ НА МЕСТЕ! if 'swap_min_sigterm' in config_dict: swap_min_sigterm = config_dict['swap_min_sigterm'] else: @@ -1129,7 +1086,6 @@ else: exit() -# НУЖНА ВАЛИДАЦИЯ НА МЕСТЕ! if 'swap_min_sigkill' in config_dict: swap_min_sigkill = config_dict['swap_min_sigkill'] else: @@ -1249,7 +1205,6 @@ else: exit() -# НА МЕСТЕ!!! if 'swap_min_warnings' in config_dict: swap_min_warnings = config_dict['swap_min_warnings'] else: @@ -1260,50 +1215,72 @@ else: ########################################################################## -# Get Kibibytes levels +# Get KiB levels if it's possible. + +# получ кб. если не кб - то процент. Если процент - находим кб ниже на +# основе полученного своптотал и процентов. -# Returns Kibibytes value if absolute value was set in config, -# or tuple with percentage -def sig_level_to_kb_swap(string): - """Returns Kibibytes value if abs val was set in config, or tuple with %""" +def get_swap_threshold_tuple(string): + # re (Num %, True) or (Num KiB, False) + """Returns KiB value if abs val was set in config, or tuple with %""" + # return tuple with abs and bool: (abs %, True) or (abs MiB, False) + if string.endswith('%'): - return float(string[:-1].strip()), True + valid = string_to_float_convert_test(string[:-1]) + if valid is None: + print('somewhere swap unit is not float_%') + exit() + + value = float(string[:-1].strip()) + if value < 0 or value > 100: + print('invalid value, must be from the range[0; 100] %') + exit() + + return value, True + elif string.endswith('M'): - return float(string[:-1].strip()) * 1024 + valid = string_to_float_convert_test(string[:-1]) + if valid is None: + print('somewhere swap unit is not float_M') + exit() + + value = float(string[:-1].strip()) * 1024 + if value < 0: + print('invalid unit in config (negative value)') + exit() + + return value, False + else: print('Invalid config file. There are invalid units somewhere\nExit') exit() -# So, get them -swap_min_sigterm_swap = sig_level_to_kb_swap(swap_min_sigterm) -swap_min_sigkill_swap = sig_level_to_kb_swap(swap_min_sigkill) - -swap_min_warnings_swap = sig_level_to_kb_swap(swap_min_warnings) +swap_min_sigterm_tuple = get_swap_threshold_tuple(swap_min_sigterm) +swap_min_sigkill_tuple = get_swap_threshold_tuple(swap_min_sigkill) +swap_min_warnings_tuple = get_swap_threshold_tuple(swap_min_warnings) -if isinstance(swap_min_sigterm_swap, tuple): - swap_term_is_percent = True - swap_min_sigterm_percent = swap_min_sigterm_swap[0] +swap_term_is_percent = swap_min_sigterm_tuple[1] +if swap_term_is_percent: + swap_min_sigterm_percent = swap_min_sigterm_tuple[0] else: - swap_term_is_percent = False - swap_min_sigterm_kb = swap_min_sigterm_swap + swap_min_sigterm_kb = swap_min_sigterm_tuple[0] -if isinstance(swap_min_sigkill_swap, tuple): - swap_kill_is_percent = True - swap_min_sigkill_percent = swap_min_sigkill_swap[0] + +swap_kill_is_percent = swap_min_sigkill_tuple[1] +if swap_kill_is_percent: + swap_min_sigkill_percent = swap_min_sigkill_tuple[0] else: - swap_kill_is_percent = False - swap_min_sigkill_kb = swap_min_sigkill_swap + swap_min_sigkill_kb = swap_min_sigkill_tuple[0] -if isinstance(swap_min_warnings_swap, tuple): - swap_warn_is_percent = True - swap_min_warnings_percent = swap_min_warnings_swap[0] +swap_warn_is_percent = swap_min_warnings_tuple[1] +if swap_warn_is_percent: + swap_min_warnings_percent = swap_min_warnings_tuple[0] else: - swap_warn_is_percent = False - swap_min_warnings_kb = swap_min_warnings_swap + swap_min_warnings_kb = swap_min_warnings_tuple[0] ########################################################################## @@ -1413,16 +1390,6 @@ if psi_support and not ignore_psi: avg_value = '' - - - - - - - - - - while True: if psi_support and not ignore_psi: @@ -1447,6 +1414,8 @@ while True: mem_available, swap_total, swap_free = check_mem_and_swap() + # если метры - получаем киб выше и сразу. см. + # 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 @@ -1457,6 +1426,9 @@ while True: if swap_warn_is_percent: swap_min_warnings_kb = swap_total * swap_min_warnings_percent / 100.0 + # в общем случае для работы нужны килобайты. Если в процентах задано - + # находим КБ тут, после получения своптотал. + mem_used_zram = check_zram() if print_mem_check_results: @@ -1503,6 +1475,8 @@ while True: # печатать так: SwapTotal = 0, ignore swapspace swap_sigterm_pc = '-' + # это для печати меминфо. Все переработать нахрен. + # далее пошло ветвление # MEM SWAP KILL @@ -1563,7 +1537,7 @@ while True: 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)),