diff --git a/README.md b/README.md index 3fa20d5..b4f8bdc 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,8 @@ https://2ch.hk/s/res/2310304.html#2311483, https://archive.li/idixk ### Особенности - задача - препятствовать зависанию системы при нехватке доступной памяти, а также корректное завершение процессов с целью увеличения объема доступной памяти -- демон на Python 3, VmRSS около 12.8 MiB -- требуется `Linux 3.14+` и `Python 3.4+` +- демон на Python 3, VmRSS не более 13 MiB +- требуется ядро `Linux 3.14` или новее - периодически проверяет объем доступной памяти, при дефиците памяти отправляет `SIGKILL` или `SIGTERM` процессу с наибольшим `oom_score` - поддержка работы со `zram`, возможность реакции на `mem_used_total` - удобный конфиг с возможностью тонкой настройки @@ -101,4 +101,3 @@ sudo ./uninstall.sh ### Известные баги В рабочем алгоритме известных нет, если найдете - пишите в [Issues](https://github.com/hakavlad/nohang/issues). -Алгоритм снова сломался, ждите релиза v0.1. diff --git a/nohang b/nohang index bf79d35..107f789 100755 --- a/nohang +++ b/nohang @@ -17,21 +17,29 @@ from argparse import ArgumentParser # - задание констант -# найден экспериментально, требует уточнения с разными ядрами и архитектурами -zram_disksize_factor = 0.0042 - -# где искать конфиг, если не указан через --config -default_configs = ('./nohang.conf', '/etc/nohang/nohang.conf') +# где искать конфиг, если не указан через опцию -c/--config CONFIG +default_configs = ( + './nohang.conf', + '/etc/nohang/nohang.conf' + ) err_mess = '\nSet up path to the valid config file with -c/--config 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 = 0.0042 + ########################################################################################### # - задание функций - -def decrease_oom_score_adj(oom_score_adj_before, oom_score_adj_after): +def func_decrease_oom_score_adj(oom_score_adj_before, oom_score_adj_after): # цикл для наполнения oom_list for i in os.listdir('/proc'): @@ -66,8 +74,8 @@ def kib_to_mib(num): return round(num / 1024.0) -def percent(n): - return round(n * 100, 1) +def percent(num): + return round(num * 100, 1) def just_percent(num): @@ -75,8 +83,8 @@ def just_percent(num): # K -> M, выравнивание по правому краю -def human(num): - return str(round(num / 1024)).rjust(5, ' ') +def human(num, lenth): + return str(round(num / 1024)).rjust(lenth, ' ') # возвращает disksize и mem_used_total по zram id @@ -114,9 +122,8 @@ def pid_to_name(pid): def find_victim_and_send_signal(signal): if decrease_oom_score_adj and root: - decrease_oom_score_adj(oom_score_adj_before, oom_score_adj_after) + func_decrease_oom_score_adj(oom_score_adj_before, oom_score_adj_after) - #print('Find victim...') oom_list = [] for i in os.listdir('/proc'): @@ -126,6 +133,8 @@ def find_victim_and_send_signal(signal): oom_score = int(rline1('/proc/' + i + '/oom_score')) except FileNotFoundError: oom_score = 0 + except ProcessLookupError: + oom_score = 0 oom_list.append((i, oom_score)) # получаем список пар (pid, oom_score) @@ -571,9 +580,8 @@ if print_config: - - - +# для рассчета ширины столбцов mem и zram +mem_len = len(str(round(mem_total / 1024.0))) ########################################################################################### @@ -600,6 +608,7 @@ while True: break + # если swap_min_sigkill задан в процентах if swap_kill_is_percent: swap_min_sigkill_kb = swap_total * swap_min_sigkill_percent / 100.0 @@ -621,15 +630,19 @@ while True: ) / 1024.0 + # для рассчета ширины столбца свопа + swap_len = len(str(round(swap_total / 1024.0))) + + # печать результатов проверк доступной памяти if print_mem_check_results: print( - 'MemAvail: {}M {}%, SwapFree: {}M {}%, MemUsedZram: {}M {}%'.format( - human(mem_available), + 'MemAvail: {}M {}% | SwapFree: {}M {}% | MemUsedZram: {}M {}%'.format( + human(mem_available, mem_len), just_percent(mem_available / mem_total), - human(swap_free), + human(swap_free, swap_len), just_percent(swap_free / (swap_total + 0.0001)), - human(mem_used_zram), + human(mem_used_zram, mem_len), just_percent(mem_used_zram / mem_total) ) )