From 27d22d41e4200bf386b95632938c74d6f67b6a5a Mon Sep 17 00:00:00 2001 From: Alexey Avramov Date: Mon, 11 Jun 2018 04:52:39 +0900 Subject: [PATCH] =?UTF-8?q?=D0=BC=D0=BD=D0=BE=D0=B6=D0=B5=D1=81=D1=82?= =?UTF-8?q?=D0=B2=D0=BE=20=D1=83=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 26 ++- nohang | 513 +++++++++++++++++++++++++++++++++++----------------- nohang.1 | 2 +- nohang.conf | 63 +++---- 4 files changed, 384 insertions(+), 220 deletions(-) diff --git a/README.md b/README.md index 5d326b6..ff7c7fa 100644 --- a/README.md +++ b/README.md @@ -47,24 +47,21 @@ https://2ch.hk/s/res/2310304.html#2311483, https://archive.li/idixk - по умолчанию высокий приоритет процесса `nice -20`, может регулироваться через конфиг - предотвращение самоубийства с помощью `self_oom_score_adj = -1000` - возможность задания `oom_score_min` для предотвращения убийства невиновных +- опциональность печати результатов проверки памяти - `min_delay_after_sigkill` для предотвращения массовых убийств - наличие `man` страницы - наличие установщика для пользователей `systemd` - протестировано на `Debian 9 x86_64`, `Debian 8 i386`, `Fedora 28 x86_64` - пример вывода с отчетом об успешной отпраке сигнала: ``` -MemAvail: 0M 0.0%, SwapFree: 985M 8.4%, MemUsedZram: 625M 10.6% -MemAvail: 0M 0.0%, SwapFree: 962M 8.2%, MemUsedZram: 626M 10.6% -MemAvail: 9M 0.1%, SwapFree: 939M 8.0%, MemUsedZram: 626M 10.7% -MemAvailable 9M < 353M and SwapFree 939M < 940M -Try to send signal 15 to process python3, Pid 3392, oom_score 818 -Success -MemAvail: 29M 0.5%, SwapFree: 2866M 24.4%, MemUsedZram: 582M 9.9% -MemAvail: 77M 1.3%, SwapFree: 5037M 42.9%, MemUsedZram: 532M 9.1% -MemAvail: 168M 2.9%, SwapFree: 8956M 76.2%, MemUsedZram: 441M 7.5% -MemAvail: 5006M 85.2%, SwapFree: 10632M 90.5%, MemUsedZram: 356M 6.1% -MemAvail: 5000M 85.1%, SwapFree: 10633M 90.5%, MemUsedZram: 356M 6.1% - +MemAvail: 0M 0.0%, SwapFree: 706M 6.0%, MemUsedZram: 357M 6.1% +MemAvail: 0M 0.0%, SwapFree: 411M 3.5%, MemUsedZram: 362M 6.2% ++ MemAvail (0M, 0.0%) < mem_min_sigterm (235M, 4.0%) + SwapFree (411M, 3.5%) < swap_min_sigterm (470M, 4.0%) + Try to send signal 15 to python3, Pid 3930, oom_score 903 + Success +MemAvail: 107M 1.8%, SwapFree: 3461M 29.5%, MemUsedZram: 311M 5.3% +MemAvail: 5159M 87.8%, SwapFree: 11311M 96.3%, MemUsedZram: 186M 3.2% ``` ### Установка и удаление для пользователей systemd @@ -91,8 +88,7 @@ sudo ./uninstall.sh ``` /etc/nohang/nohang.conf ``` -К опциям прилагается описание. Отредактируйте значения параметров в соответствии с вашими предпочтениями. +К опциям прилагается описание. Отредактируйте значения параметров в соответствии с вашими предпочтениями и перезапустите сервис командой `sudo systemctl restart nohang`. ### Известные баги -Известных нет, если найдете - пишите в [Issues](https://github.com/hakavlad/nohang/issues). - +В рабочем алгоритме известных нет, если найдете - пишите в [Issues](https://github.com/hakavlad/nohang/issues). diff --git a/nohang b/nohang index 9a8fee2..d8d3291 100755 --- a/nohang +++ b/nohang @@ -8,40 +8,297 @@ from operator import itemgetter from time import sleep from argparse import ArgumentParser +# найден экспериментально, требует уточнения с разными ядрами и архитектурами +zram_disksize_factor = 0.0042 +# где искать конфиг, если не указан через --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' + + +# парсинг аргументов командной строки parser = ArgumentParser() parser.add_argument( '-c', '--config', - help='path to config file, default values: ./nohang.conf, /etc/nohang/nohang.conf', + help='path to the config file, default values: ./nohang.conf, /etc/nohang/nohang.conf', default=None, type=str ) + arg_config = parser.parse_args().config -# ветвление требует переработки и лучшей обработки исключений -if arg_config != None: - if os.path.exists: + +if arg_config is None: + + # print('конфиг не задан через опцию -с/--config, берем его из дефолтных путей') + del arg_config + + config = None + for i in default_configs: + if os.path.exists(i): + config = i + break + if config is None: + print('По дефолтным путям конфиг не найден', err_mess) + exit() + +else: + + # print('через опцию задан путь к конфигу {}'.format(arg_config)) + + if os.path.exists(arg_config): config = arg_config else: - print('Указанный конфиг файл {} не существует!'.format(arg_config)) + print('нет файла по указанному пути: {}'.format(arg_config), err_mess) exit() -elif os.path.exists('./nohang.conf'): - config = './nohang.conf' -elif os.path.exists('/etc/nohang/nohang.conf'): - config = '/etc/nohang/nohang.conf' -else: - print('Пожалуйста, укажите путь к конфигу опцией -c или --config') + + + + +print('path to config:', config) + + + + + +try: + with open(config) as f: + config_dict = dict() + for line in f: + a = line.startswith('#') + b = line.startswith('\n') + c = line.startswith('\t') + d = line.startswith(' ') + if not a and not b and not c and not d: + a = line.split('=') + config_dict[a[0].strip()] = a[1].strip() +except PermissionError: + print('PermissionError', err_mess) + exit() +except UnicodeDecodeError: + print('UnicodeDecodeError', err_mess) + exit() +except IsADirectoryError: + print('IsADirectoryError', err_mess) + exit() +except IndexError: + print('IndexError', err_mess) exit() -# найден экспериментально, требует уточнения с разными ядрами и архитектурами -zram_disksize_factor = 0.0042 + + + +if 'print_mem_check_results' in config_dict: + print_mem_check_results = config_dict['print_mem_check_results'] + if print_mem_check_results == 'True': + print_mem_check_results = True + elif print_mem_check_results == 'False': + print_mem_check_results = False + else: + print( + 'invalid mlockall value {} (should be True or False), exit!'.format( + print_mem_check_results + ) + ) + exit() + print('print_mem_check_results: {}'.format(print_mem_check_results)) +else: + print('print_mem_check_results not in config, exit!') + exit() + + +if 'mlockall' in config_dict: + mlockall = config_dict['mlockall'] + if mlockall == 'True': + mlockall = True + elif mlockall == 'False': + mlockall = False + else: + print( + 'invalid mlockall value {} (should be True or False), exit!'.format( + mlockall + ) + ) + exit() + print('mlockall: {}'.format(mlockall)) +else: + print('mlockall not in config, exit!') + exit() + + +if 'self_nice' in config_dict: + self_nice = int(config_dict['self_nice']) + print('self_nice: {}'.format(self_nice)) +else: + print('self_nice not in config, exit!') + exit() + + +if 'self_oom_score_adj' in config_dict: + self_oom_score_adj = int(config_dict['self_oom_score_adj']) + print('self_oom_score_adj: {}'.format(self_oom_score_adj)) +else: + print('self_oom_score_adj not in config, exit!') + exit() + + +if 'rate_mem' in config_dict: + rate_mem = float(config_dict['rate_mem']) + if rate_mem <= 0: + print('rate_mem должен быть положительным') + exit() + print('rate_mem: {}'.format(rate_mem)) +else: + print('rate_mem not in config, exit!') + exit() + + +if 'rate_swap' in config_dict: + rate_swap = float(config_dict['rate_swap']) + if rate_swap <= 0: + print('rate_swap должен быть положительным') + exit() + print('rate_swap: {}'.format(rate_swap)) +else: + print('rate_swap not in config, exit!') + exit() + + +if 'rate_zram' in config_dict: + rate_zram = float(config_dict['rate_zram']) + if rate_zram <= 0: + print('rate_zram должен быть положительным') + exit() + print('rate_zram: {}'.format(rate_zram)) +else: + print('rate_zram not in config, exit!') + exit() + + +if 'mem_min_sigterm' in config_dict: + mem_min_sigterm = config_dict['mem_min_sigterm'] + print('mem_min_sigterm: {}'.format(mem_min_sigterm)) +else: + print('mem_min_sigterm not in config, exit!') + exit() + + +if 'mem_min_sigkill' in config_dict: + mem_min_sigkill = config_dict['mem_min_sigkill'] + print('mem_min_sigkill: {}'.format(mem_min_sigkill)) +else: + print('mem_min_sigkill not in config, exit!') + exit() + + +if 'swap_min_sigterm' in config_dict: + swap_min_sigterm = config_dict['swap_min_sigterm'] + print('swap_min_sigterm: {}'.format(swap_min_sigterm)) +else: + print('swap_min_sigterm not in config, exit!') + exit() + + +if 'swap_min_sigkill' in config_dict: + swap_min_sigkill = config_dict['swap_min_sigkill'] + print('swap_min_sigkill: {}'.format(swap_min_sigkill)) +else: + print('swap_min_sigkill not in config, exit!') + exit() + + +if 'zram_max_sigterm' in config_dict: + zram_max_sigterm = config_dict['zram_max_sigterm'] + print('zram_max_sigterm: {}'.format(zram_max_sigterm)) +else: + print('zram_max_sigterm not in config, exit!') + exit() + + +if 'zram_max_sigkill' in config_dict: + zram_max_sigkill = config_dict['zram_max_sigkill'] + print('zram_max_sigkill: {}'.format(zram_max_sigkill)) +else: + print('zram_max_sigkill not in config, exit!') + exit() + + +if 'min_delay_after_sigterm' in config_dict: + min_delay_after_sigterm = float(config_dict['min_delay_after_sigterm']) + print('min_delay_after_sigterm: {}'.format(min_delay_after_sigterm)) +else: + print('min_delay_after_sigterm not in config, exit!') + exit() + + +if 'min_delay_after_sigkill' in config_dict: + min_delay_after_sigkill = float(config_dict['min_delay_after_sigkill']) + print('min_delay_after_sigkill: {}'.format(min_delay_after_sigkill)) +else: + print('min_delay_after_sigkill not in config, exit!') + exit() + + +if 'oom_score_min' in config_dict: + oom_score_min = int(config_dict['oom_score_min']) + print('oom_score_min: {}'.format(oom_score_min)) +else: + print('oom_score_min not in config, exit!') + exit() + + +if 'decrease_oom_score_adj_enable' in config_dict: + decrease_oom_score_adj_enable = config_dict['decrease_oom_score_adj_enable'] + if decrease_oom_score_adj_enable == 'True': + decrease_oom_score_adj_enable = True + elif decrease_oom_score_adj_enable == 'False': + decrease_oom_score_adj_enable = False + else: + print( + 'invalid mlockall value {} (should be True or False), exit!'.format( + decrease_oom_score_adj_enable + ) + ) + exit() + print('decrease_oom_score_adj_enable: {}'.format(decrease_oom_score_adj_enable)) +else: + print('decrease_oom_score_adj_enable not in config, exit!') + exit() + + +if 'oom_score_adj_before' in config_dict: + oom_score_adj_before = int(config_dict['oom_score_adj_before']) + print('oom_score_adj_before: {}'.format(oom_score_adj_before)) +else: + print('oom_score_adj_before not in config, exit!') + exit() + + +if 'oom_score_adj_after' in config_dict: + oom_score_adj_after = config_dict['oom_score_adj_after'] + print('oom_score_adj_after: {}'.format(oom_score_adj_after)) +else: + print('oom_score_adj_after not in config, exit!') + exit() + + + ########################################################################################### + + + + + + + + def decrease_oom_score_adj(oom_score_adj_before, oom_score_adj_after): #print('Decrease oom_score_adj...') # цикл для наполнения oom_list @@ -72,30 +329,14 @@ def rline1(path): def write(path, string): with open(path, 'w') as f: f.write(string) +# дикриз не от рута -# возвращает словарь с параметрами из конфига -def config_parser(config): - if os.path.exists(config): - try: - with open(config) as f: - name_value_dict = dict() - for line in f: - a = line.startswith('#') - b = line.startswith('\n') - c = line.startswith('\t') - d = line.startswith(' ') - if not a and not b and not c and not d: - a = line.split('=') - name_value_dict[a[0].strip()] = a[1].strip() - return name_value_dict - except PermissionError: - return 2 - else: - return 1 +def percent(n): + return round(n * 100, 1) -def to_percent(num): +def just_percent(num): return str(round(num * 100, 1)).rjust(5, ' ') @@ -163,22 +404,22 @@ def find_victim_and_send_signal(signal): name = pid_to_name(pid) print( - 'Try to send signal {} to process {}, Pid {}, oom_score {}'.format( + ' Try to send signal {} to {}, Pid {}, oom_score {}'.format( signal, name, pid, oom_score ) ) try: os.kill(int(pid), signal) - print('Success') + print(' Success') except ProcessLookupError: - print('No such process') + print(' No such process') except PermissionError: - print('Operation not permitted') + print(' Operation not permitted') else: - print('oom_score {} < oom_score_min {}'.format(oom_score, oom_score_min)) + print(' oom_score {} < oom_score_min {}'.format(oom_score, oom_score_min)) ########################################################################################### @@ -206,105 +447,21 @@ mem_total = int(mem_list[0].split(':')[1].split(' ')[-2]) -config_dict = config_parser(config) - -if config_dict is 1: - print('config {} does not exists'.format(config)) - -elif config_dict is 2: - print('cannot read config {}, permission error'.format(config)) - -else: - print('config: {}\n'.format(config)) - - if 'mlockall' in config_dict: - mlockall = config_dict['mlockall'] - if mlockall == 'True': - mlockall = True - print('mlockall: {}'.format(mlockall)) - - if 'self_nice' in config_dict: - self_nice = int(config_dict['self_nice']) - print('self_nice: {}'.format(self_nice)) - - if 'self_oom_score_adj' in config_dict: - self_oom_score_adj = int(config_dict['self_oom_score_adj']) - print('self_oom_score_adj: {}'.format(self_oom_score_adj)) - - if 'rate_mem' in config_dict: - rate_mem = float(config_dict['rate_mem']) - print('rate_mem: {}'.format(rate_mem)) - - if 'rate_swap' in config_dict: - rate_swap = float(config_dict['rate_swap']) - print('rate_swap: {}'.format(rate_swap)) - - if 'rate_zram' in config_dict: - rate_zram = float(config_dict['rate_zram']) - print('rate_zram: {}'.format(rate_zram)) - - if 'mem_min_sigterm' in config_dict: - mem_min_sigterm = config_dict['mem_min_sigterm'] - print('mem_min_sigterm: {}'.format(mem_min_sigterm)) - - if 'mem_min_sigkill' in config_dict: - mem_min_sigkill = config_dict['mem_min_sigkill'] - print('mem_min_sigkill: {}'.format(mem_min_sigkill)) - - if 'swap_min_sigterm' in config_dict: - swap_min_sigterm = config_dict['swap_min_sigterm'] - print('swap_min_sigterm: {}'.format(swap_min_sigterm)) - - if 'swap_min_sigkill' in config_dict: - swap_min_sigkill = config_dict['swap_min_sigkill'] - print('swap_min_sigkill: {}'.format(swap_min_sigkill)) - - if 'zram_max_sigterm' in config_dict: - zram_max_sigterm = config_dict['zram_max_sigterm'] - print('zram_max_sigterm: {}'.format(zram_max_sigterm)) - - if 'zram_max_sigkill' in config_dict: - zram_max_sigkill = config_dict['zram_max_sigkill'] - print('zram_max_sigkill: {}'.format(zram_max_sigkill)) - - if 'min_delay_after_sigterm' in config_dict: - min_delay_after_sigterm = float(config_dict['min_delay_after_sigterm']) - print('min_delay_after_sigterm: {}'.format(min_delay_after_sigterm)) - - if 'min_delay_after_sigkill' in config_dict: - min_delay_after_sigkill = float(config_dict['min_delay_after_sigkill']) - print('min_delay_after_sigkill: {}'.format(min_delay_after_sigkill)) - - if 'oom_score_min' in config_dict: - oom_score_min = int(config_dict['oom_score_min']) - print('oom_score_min: {}'.format(oom_score_min)) - - if 'decrease_oom_score_adj_enable' in config_dict: - decrease_oom_score_adj_enable = config_dict['decrease_oom_score_adj_enable'] - if decrease_oom_score_adj_enable == 'True': - decrease_oom_score_adj_enable = True - print('decrease_oom_score_adj_enable: {}'.format(decrease_oom_score_adj_enable)) - - if 'oom_score_adj_before' in config_dict: - oom_score_adj_before = int(config_dict['oom_score_adj_before']) - print('oom_score_adj_before: {}'.format(oom_score_adj_before)) - - if 'oom_score_adj_after' in config_dict: - oom_score_adj_after = config_dict['oom_score_adj_after'] - print('oom_score_adj_after: {}'.format(oom_score_adj_after)) - - - - def sig_level_to_kb(string): if string.endswith('%'): return float(string[:-1].strip()) / 100 * mem_total - if string.endswith('K'): + elif string.endswith('K'): return float(string[:-1].strip()) - if string.endswith('M'): + elif string.endswith('M'): return float(string[:-1].strip()) * 1024 - if string.endswith('G'): + elif string.endswith('G'): return float(string[:-1].strip()) * 1048576 + else: + print('Конфиг инвалид, где-то неверно указаны единицы измерения') + exit() + + + mem_min_sigterm_kb = sig_level_to_kb(mem_min_sigterm) mem_min_sigkill_kb = sig_level_to_kb(mem_min_sigkill) @@ -313,7 +470,6 @@ zram_max_sigkill_kb = sig_level_to_kb(zram_max_sigkill) - # возвращает число килобайт при задании в конфиге абсолютного значения, # или кортеж с числом процентов def sig_level_to_kb_swap(string): @@ -321,12 +477,16 @@ def sig_level_to_kb_swap(string): if string.endswith('%'): return float(string[:-1].strip()), True - if string.endswith('K'): + elif string.endswith('K'): return float(string[:-1].strip()) - if string.endswith('M'): + elif string.endswith('M'): return float(string[:-1].strip()) * 1024 - if string.endswith('G'): + elif string.endswith('G'): return float(string[:-1].strip()) * 1048576 + else: + print('Конфиг инвалид, где-то неверно указаны единицы измерения') + exit() + # получаем число килобайт или кортеж с процентами swap_min_sigterm_swap = sig_level_to_kb_swap(swap_min_sigterm) @@ -400,7 +560,10 @@ def kib_to_mib(num): ########################################################################################### -print() + + + +print('Start monitoring...') # рабочий цикл while True: @@ -457,27 +620,44 @@ while True: t = t_mem_zram - # печать состояния памяти - print( - 'MemAvail: {}M {}%, SwapFree: {}M {}%, MemUsedZram: {}M {}%'.format( - human(mem_available), - to_percent(mem_available / mem_total), - human(swap_free), - to_percent(swap_free / (swap_total + 0.0001)), - human(mem_used_zram), - to_percent(mem_used_zram / mem_total) + if print_mem_check_results: + print( + 'MemAvail: {}M {}%, SwapFree: {}M {}%, MemUsedZram: {}M {}%'.format( + human(mem_available), + just_percent(mem_available / mem_total), + human(swap_free), + just_percent(swap_free / (swap_total + 0.0001)), + human(mem_used_zram), + just_percent(mem_used_zram / mem_total) + ) ) - ) + + + + if swap_total > swap_min_sigkill_kb: + swap_sigkill_pc = percent(swap_min_sigkill_kb / (swap_total + 1)) + else: + swap_sigkill_pc = '-' + + if swap_total > swap_min_sigterm_kb: + swap_sigterm_pc = percent(swap_min_sigterm_kb / (swap_total + 1)) + else: + swap_sigterm_pc = '-' # MEM SWAP KILL if mem_available <= mem_min_sigkill_kb and swap_free <= swap_min_sigkill_kb: print( - 'MemAvailable {}M < {}M and SwapFree {}M < {}M'.format( - kib_to_mib(mem_available), - kib_to_mib(mem_min_sigkill_kb), - kib_to_mib(swap_free), - kib_to_mib(swap_min_sigkill_kb) + '+ MemAvail ({}M, {}%) < mem_min_sigkill ({}M, {}%)\n SwapFree' \ + ' ({}M, {}%) < swap_min_sigkill ({}M, {}%)'.format( + 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(swap_free), + percent(swap_free / (swap_total + 0.0001)), + kib_to_mib(swap_min_sigkill_kb), + swap_sigkill_pc ) ) find_victim_and_send_signal(9) @@ -487,9 +667,11 @@ while True: # MEM ZRAM KILL if mem_used_zram >= zram_max_sigkill_kb: print( - 'MemUsedZram {}M > {}M'.format( - kib_to_mib(mem_used_zram), - kib_to_mib(zram_max_sigkill_kb) + '+ MemUsedZram ({}M, {}%) > zram_max_sigkill ({}M, {}%)'.format( + kib_to_mib(mem_used_zram), + percent(mem_used_zram / mem_total), + kib_to_mib(zram_max_sigkill_kb), + percent(zram_max_sigkill_kb / mem_total) ) ) find_victim_and_send_signal(9) @@ -499,11 +681,16 @@ while True: # MEM SWAP TERM if mem_available <= mem_min_sigterm_kb and swap_free <= swap_min_sigterm_kb: print( - 'MemAvailable {}M < {}M and SwapFree {}M < {}M'.format( - kib_to_mib(mem_available), - kib_to_mib(mem_min_sigterm_kb), - kib_to_mib(swap_free), - kib_to_mib(swap_min_sigterm_kb) + '+ MemAvail ({}M, {}%) < mem_min_sigterm ({}M, {}%)\n SwapFree' \ + ' ({}M, {}%) < swap_min_sigterm ({}M, {}%)'.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), + kib_to_mib(swap_free), + percent(swap_free / (swap_total + 0.0001)), + kib_to_mib(swap_min_sigterm_kb), + swap_sigterm_pc ) ) find_victim_and_send_signal(15) @@ -512,9 +699,11 @@ while True: # MEM ZRAM TERM if mem_used_zram >= zram_max_sigterm_kb: print( - 'MemUsedZram {}M > {}M'.format( - kib_to_mib(mem_used_zram), - kib_to_mib(zram_max_sigterm_kb) + '+ MemUsedZram ({}M, {}%) > zram_max_sigterm ({}M, {}%)'.format( + 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(15) diff --git a/nohang.1 b/nohang.1 index 9d4ea95..956fe6a 100644 --- a/nohang.1 +++ b/nohang.1 @@ -13,7 +13,7 @@ Nohang - аналог earlyoom с поддержкой zram и SIGTERM. При .TP .BI \-c " CONFIG", .BI \-\-config " CONFIG" -path to config file, default values: +path to the config file, default values: .I ./nohang.conf, .I /etc/nohang/nohang.conf .TP diff --git a/nohang.conf b/nohang.conf index 33a9179..28a1c9d 100644 --- a/nohang.conf +++ b/nohang.conf @@ -7,12 +7,18 @@ и табуляций. Инлайновые комментарии запрещены. Пробелы допустиы внутри строк в любом количестве. - В конце конфига перечислены значения по умолчанию. +##################################################################### + + Печатать ли результаты измерения доступной памяти. + Допустимые значения: True и False + +print_mem_check_results = True ##################################################################### True - заблокировать процесс в памяти для запрета его своппинга. False - не блокировать. Значения чувствительны к регистру! + Требует рут прав. mlockall = True @@ -20,6 +26,7 @@ mlockall = True Повысить приоритет процесса, установив niceness -20 Допустимые значения - целые числа из диапазона [-20; 19] + Требует рут прав. self_nice = -20 @@ -28,6 +35,7 @@ self_nice = -20 Задать oom_score_adj для процесса. Задание значения -1000 запретит самоубийство. Допустимые значения - целые числа из диапазона [-1000; 1000] + Требует рут прав. self_oom_score_adj = -1000 @@ -38,8 +46,8 @@ self_oom_score_adj = -1000 Уменьшение коэффициентов способно снизить нагрузку на прцессор и увеличить периоды между проверками памяти. - Почему три коэффициента, а не один? - Потому что - скорость наполнения свопа обычно ниже скорости наполнения RAM. + Почему три коэффициента, а не один? - Потому что скорость + наполнения свопа обычно ниже скорости наполнения RAM. Можно для свопа задать более низкую интенсивность мониторинга без ущерба для предотвращения нехватки памяти и тем самым снизить нагрузку на процессор. @@ -49,7 +57,7 @@ self_oom_score_adj = -1000 памяти. rate_mem = 6 -rate_swap = 2 +rate_swap = 0.2 rate_zram = 1 ##################################################################### @@ -67,10 +75,11 @@ rate_zram = 1 mem_min_sigterm = 0.5 G swap_min_sigkill = 200 M -mem_min_sigterm = 6 % -mem_min_sigkill = 3 % -swap_min_sigterm = 8 % -swap_min_sigkill = 4 % +mem_min_sigterm = 4% +mem_min_sigkill = 2% + +swap_min_sigterm = 4% +swap_min_sigkill = 2% Задание общей доли zram в памяти, при превышении которой происходит отправка соответствующих сигналов. @@ -91,7 +100,7 @@ zram_max_sigkill = 65 % пойдет не так. Значение должно быть целым числом из диапазона [0; 1000] -oom_score_min = 10 +oom_score_min = 15 ##################################################################### @@ -115,40 +124,10 @@ min_delay_after_sigkill = 3 False - не изменять oom_score_adj процессов перед поиском жертвы. Значения чувствительны к регистру! -decrease_oom_score_adj_enable = False + Требует рут прав. + +decrease_oom_score_adj_enable = True oom_score_adj_before = 50 oom_score_adj_after = 10 -##################################################################### -##################################################################### -##################################################################### -##################################################################### -##################################################################### - - Значения по умолчанию - - mlockall = True - self_nice = -20 - self_oom_score_adj = -1000 - - rate_mem = 6 - rate_swap = 2 - rate_zram = 1 - - mem_min_sigterm = 6 % - mem_min_sigkill = 3 % - swap_min_sigterm = 8 % - swap_min_sigkill = 4 % - zram_max_sigterm = 60 % - zram_max_sigkill = 65 % - - oom_score_min = 10 - - min_delay_after_sigterm = 0.1 - min_delay_after_sigkill = 3 - - decrease_oom_score_adj_enable = False - oom_score_adj_before = 50 - oom_score_adj_after = 10 -