diff --git a/README.md b/README.md index 1a4afd9..5d326b6 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ The No Hang Daemon ================== -`Nohang` - аналог [earlyoom](https://github.com/rfjakob/earlyoom) с поддержкой `zram` и `SIGTERM`. При дефиците доступной памяти `hohang` корректно завершает наиболее прожорливые процессы сигналом `SIGTERM`, тем самым препятствуя зависанию, а также избыточному убийству процессов ядерным `OOM killer`'ом. +`Nohang` - аналог [earlyoom](https://github.com/rfjakob/earlyoom) с поддержкой `zram` и `SIGTERM`. При дефиците доступной памяти `nohang` корректно завершает наиболее прожорливые процессы сигналом `SIGTERM`, тем самым препятствуя зависанию, а также избыточному убийству процессов ядерным `OOM killer`'ом. ### Зачем это нужно? @@ -25,25 +25,25 @@ https://www.linux.org.ru/forum/talks/12684213?lastmod=1466676523241#comment-1268 "И IRL ты никогда не знаешь, в какой момент момент твои данные перестанут умещаться в оперативку. Потому zram -- удел embedded систем, где это может быть детерминировано." https://2ch.hk/s/res/2310304.html#2311483, https://archive.li/idixk -Nohang позволяет избавиться от перечисленных выше проблем, корректно завершая наиболее прожорливые процессы сигналом `SIGTERM` не дожидаясь когда система "встанет колом". `Nohang` позволяет не бояться зависаний при использовании `zram`. +`Nohang` позволяет избавиться от перечисленных выше проблем, корректно завершая наиболее прожорливые процессы сигналом `SIGTERM` не дожидаясь когда система "встанет колом". `Nohang` позволяет не бояться зависаний при использовании `zram`. ### Зачем нужен nohang, если уже есть earlyoom? - `earlyoom` завершает (точнее убивает) процессы исключительно с помощью сигнала `SIGKILL`, в то время как `nohang` дает возможность сначала отправлять `SIGTERM`, и только если процесс не реагирует на `SIGTERM` - отправляется сигнал `SIGKILL`. -- `earlyoom` не поддерживает работу со `zram` и не реагирует на общую долю `zram` в памяти (`mem_used_total`). Это может привести к тому, что система все также встанет колом, как если бы `earlyoom` и не было (если `disksize` большой, а энтропия сжимаемых данных велика). `Nohang` позволяет избавиться от этой проблемы. По умолчанию если доля zram достигнет 60% памяти - будет отправлен сигнал `SIGTERM` процессу с наибольшим `oom_score`. +- `earlyoom` не поддерживает работу со `zram` и не реагирует на общую долю `zram` в памяти (`mem_used_total`). Это может привести к тому, что система все также встанет колом, как если бы `earlyoom` и не было (если `disksize` большой, а энтропия сжимаемых данных велика). `Nohang` позволяет избавиться от этой проблемы. По умолчанию если доля `zram` достигнет 60% памяти - будет отправлен сигнал `SIGTERM` процессу с наибольшим `oom_score`. ### Особенности - задача - препятствовать зависанию системы при нехватке доступной памяти, а также корректное завершение процессов с целью увеличения объема доступной памяти -- демон на python3, RSS около 12 MiB -- требуется Linux 3.14+ и Python 3.4+ +- демон на Python 3, VmRSS около 12 MiB +- требуется `Linux 3.14+` и `Python 3.4+` - периодически проверяет размеры доступной памяти, при дефиците памяти отправляет `SIGKILL` или `SIGTERM` процессу с наибольшим `oom_score` - поддержка работы со `zram`, возможность реакции на `mem_used_total` - удобный конфиг с возможностью тонкой настройки -- возможность раздельного задания уровней `MemAvailable`, `SwapFree`, `mem_used_total` для отпраки `SIGTERM` и `SIGKILL`, возможность задания в %, KiB, MiB, GiB -- возможность снижения `oom_score_adj` процессов, чьи `oom_score_adj` завышены (актуально для chromium) +- возможность раздельного задания уровней `MemAvailable`, `SwapFree`, `mem_used_total` для отпраки `SIGTERM` и `SIGKILL`, возможность задания в процентах (%), кибибайтах (K), мебибайтах (M), гибибайтах (G) +- возможность снижения `oom_score_adj` процессов, чьи `oom_score_adj` завышены (актуально для `chromium`) - лучший алгоритм выбора периодов между проверками доступной памяти: при больших объемах доступной памяти нет смысла проверять ее состояние часто, поэтому период проверки уменьшается по мере уменьшения размера доступной памяти - интенсивность мониторинга можно гибко настраивать (параметры конфига `rate_mem`, `rate_swap`, `rate_zram`) -- память заблокирована с помощью `mlockall()` для предотвращения своппинга процесса +- по умолчанию память заблокирована с помощью `mlockall()` для предотвращения своппинга процесса - по умолчанию высокий приоритет процесса `nice -20`, может регулироваться через конфиг - предотвращение самоубийства с помощью `self_oom_score_adj = -1000` - возможность задания `oom_score_min` для предотвращения убийства невиновных @@ -51,12 +51,20 @@ Nohang позволяет избавиться от перечисленных - наличие `man` страницы - наличие установщика для пользователей `systemd` - протестировано на `Debian 9 x86_64`, `Debian 8 i386`, `Fedora 28 x86_64` -- вывод отчета об убийствах такого вида +- пример вывода с отчетом об успешной отпраке сигнала: ``` -2018-Jun-07 04:55:16 Mem: 0 M, Swap: 454 M, Zram: 488 M -mem_available < mem_term_level and swap_free < swap_term_level -Try to send signal 15 to process python3, Pid 7281, oom_score 893 +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% + ``` ### Установка и удаление для пользователей systemd @@ -78,7 +86,7 @@ sudo ./uninstall.sh ``` ### Настройка -Nohang настраивается с помощью [конфига](https://github.com/hakavlad/nohang/blob/master/nohang.conf), расположенного после установки +`Nohang` настраивается с помощью [конфига](https://github.com/hakavlad/nohang/blob/master/nohang.conf), расположенного после установки по адресу ``` /etc/nohang/nohang.conf @@ -86,6 +94,5 @@ Nohang настраивается с помощью [конфига](https://git К опциям прилагается описание. Отредактируйте значения параметров в соответствии с вашими предпочтениями. ### Известные баги -На самом деле алгоритм кривой, и киллер может вовремя не запуститься. Дождитесь исправлений. Текущая версия программы - пререлизная, ждите выпуска стабильной 0.1 версии. - +Известных нет, если найдете - пишите в [Issues](https://github.com/hakavlad/nohang/issues). diff --git a/install.sh b/install.sh index 3aa859d..285dda7 100755 --- a/install.sh +++ b/install.sh @@ -1,20 +1,20 @@ #!/bin/bash -v -cp nohang /usr/local/bin/ +cp -f nohang /usr/local/bin/ chmod 755 /usr/local/bin/nohang mkdir /etc/nohang chmod 755 /etc/nohang -cp nohang.conf /etc/nohang/ +cp -f nohang.conf /etc/nohang/ chmod 644 /etc/nohang/nohang.conf gzip -k nohang.1 mkdir /usr/local/share/man/man1 chmod 755 /usr/local/share/man/man1 -cp nohang.1.gz /usr/local/share/man/man1/ +cp -f nohang.1.gz /usr/local/share/man/man1/ chmod 644 /usr/local/share/man/man1/nohang.1.gz -cp nohang.service /etc/systemd/system/ +cp -f nohang.service /etc/systemd/system/ chmod 644 /etc/systemd/system/nohang.service systemctl daemon-reload systemctl enable nohang diff --git a/nohang b/nohang index cbbe2c5..4d11665 100755 --- a/nohang +++ b/nohang @@ -1,29 +1,50 @@ #!/usr/bin/env python3 -# nohang - no hang daemon +# Nohang - No Hang Daemon import os from ctypes import CDLL from operator import itemgetter from signal import SIGKILL, SIGTERM from time import gmtime, strftime, sleep, time +import argparse -if os.path.exists('./nohang.conf'): + +parser = argparse.ArgumentParser() +parser.add_argument( + '-c', + '--config', + help='path to 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: + config = arg_config + else: + print('Указанный конфиг файл {} не существует!'.format(arg_config)) + exit() +elif os.path.exists('./nohang.conf'): config = './nohang.conf' - print('config: {}'.format(config)) elif os.path.exists('/etc/nohang/nohang.conf'): config = '/etc/nohang/nohang.conf' - print('config: {}'.format(config)) else: - print('укажите путь к конфигу опцией --config') + print('Пожалуйста, укажите путь к конфигу опцией -c или --config') exit() +# найден экспериментально, требует уточнения с разными ядрами и архитектурами zram_disksize_factor = 0.0042 + ########################################################################################### + def decrease_oom_score_adj(oom_score_adj_before, oom_score_adj_after): - print('decrease oom_score_adj...') + #print('Decrease oom_score_adj...') # цикл для наполнения oom_list for i in os.listdir('/proc'): @@ -40,6 +61,7 @@ def decrease_oom_score_adj(oom_score_adj_before, oom_score_adj_after): except ProcessLookupError: pass + # чтение первой строки файла def rline1(path): with open(path) as f: @@ -53,6 +75,7 @@ def write(path, string): f.write(string) +# возвращает словарь с параметрами из конфига def config_parser(config): if os.path.exists(config): try: @@ -73,24 +96,10 @@ def config_parser(config): return 1 -def sig_level_to_kb(string): - if string.endswith('%'): - return mem_total * float(string[:-1].strip()) / 100 - if string.endswith('KiB'): - return float(string[:-3].strip()) - if string.endswith('MiB'): - return float(string[:-3].strip()) * 1024 - if string.endswith('GiB'): - return float(string[:-3].strip()) * 1048576 +def to_percent(num): + return str(round(num * 100, 1)).rjust(5, ' ') -# перевод дроби в проценты -def percent(num): - a = str(round(num * 100, 1)).split('.') - a0 = a[0].rjust(3, ' ') - a1 = a[1] - return '{}.{}'.format(a0, a1) - # K -> M, выравнивание по правому краю def human(num): return str(round(num / 1024)).rjust(5, ' ') @@ -148,7 +157,7 @@ def find_victim(signal): if decrease_oom_score_adj_enable and root: decrease_oom_score_adj(oom_score_adj_before, oom_score_adj_after) - print('find victim...') + #print('Find victim...') oom_list = [] @@ -184,15 +193,15 @@ def find_victim(signal): try: os.kill(int(pid), signal) - print('Success\n') + print('Success') except ProcessLookupError: - print('No such process\n') + print('No such process') except PermissionError: - print('Operation not permitted\n') + print('Operation not permitted') else: - print('\noom_score {} < oom_score_min {}\n'.format(oom_score, oom_score_min)) + print('oom_score {} < oom_score_min {}'.format(oom_score, oom_score_min)) ########################################################################################### @@ -202,7 +211,6 @@ def find_victim(signal): # ищем позиции - with open('/proc/meminfo') as file: mem_list = file.readlines() @@ -219,13 +227,11 @@ swap_free_index = swap_total_index + 1 mem_total = int(mem_list[0].split(':')[1].split(' ')[-2]) -############################################################################################### + + config_dict = config_parser(config) -print(config_dict, '\n') - - if config_dict is 1: print('config {} does not exists'.format(config)) @@ -277,12 +283,6 @@ else: swap_min_sigkill = config_dict['swap_min_sigkill'] print('swap_min_sigkill: {}'.format(swap_min_sigkill)) - if 'check_zram' in config_dict: - check_zram = config_dict['check_zram'] - if check_zram == 'yes': - check_zram = True - print('check_zram: {}'.format(check_zram)) - if 'zram_max_sigterm' in config_dict: zram_max_sigterm = config_dict['zram_max_sigterm'] print('zram_max_sigterm: {}'.format(zram_max_sigterm)) @@ -295,7 +295,6 @@ else: 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)) @@ -318,54 +317,70 @@ else: oom_score_adj_after = config_dict['oom_score_adj_after'] print('oom_score_adj_after: {}'.format(oom_score_adj_after)) - if 'use_lists' in config_dict: - use_lists = config_dict['use_lists'] - if use_lists == 'yes': - use_lists = True - print('use_lists: {}'.format(use_lists)) - if 'white_list' in config_dict: - white_list = config_dict['white_list'].split(',') - for i in range(len(white_list)): - white_list[i] = white_list[i].strip() - print('white_list: {}'.format(white_list)) - if 'avoid_list' in config_dict: - avoid_list = config_dict['avoid_list'].split(',') - for i in range(len(avoid_list)): - avoid_list[i] = avoid_list[i].strip() - print('avoid_list: {}'.format(avoid_list)) - if 'avoid_ratio' in config_dict: - avoid_ratio = float(config_dict['avoid_ratio']) - print('avoid_ratio: {}'.format(avoid_ratio)) - if 'black_list' in config_dict: - black_list = config_dict['black_list'].split(',') - for i in range(len(black_list)): - black_list[i] = black_list[i].strip() - print('black_list: {}'.format(black_list)) - - if 'prefer_list' in config_dict: - prefer_list = config_dict['prefer_list'].split(',') - for i in range(len(prefer_list)): - prefer_list[i] = prefer_list[i].strip() - print('prefer_list: {}'.format(prefer_list)) - - if 'prefer_ratio' in config_dict: - prefer_ratio = float(config_dict['prefer_ratio']) - print('prefer_ratio: {}\n'.format(prefer_ratio)) +def sig_level_to_kb(string): + if string.endswith('%'): + return float(string[:-1].strip()) / 100 * mem_total + if string.endswith('K'): + return float(string[:-1].strip()) + if string.endswith('M'): + return float(string[:-1].strip()) * 1024 + if string.endswith('G'): + return float(string[:-1].strip()) * 1048576 mem_min_sigterm_kb = sig_level_to_kb(mem_min_sigterm) mem_min_sigkill_kb = sig_level_to_kb(mem_min_sigkill) -swap_min_sigterm_kb = sig_level_to_kb(swap_min_sigterm) -swap_min_sigkill_kb = sig_level_to_kb(swap_min_sigkill) zram_max_sigterm_kb = sig_level_to_kb(zram_max_sigterm) zram_max_sigkill_kb = sig_level_to_kb(zram_max_sigkill) + + + +# возвращает число килобайт при задании в конфиге абсолютного значения, +# или кортеж с числом процентов +def sig_level_to_kb_swap(string): + + if string.endswith('%'): + return float(string[:-1].strip()), True + + if string.endswith('K'): + return float(string[:-1].strip()) + if string.endswith('M'): + return float(string[:-1].strip()) * 1024 + if string.endswith('G'): + return float(string[:-1].strip()) * 1048576 + +# получаем число килобайт или кортеж с процентами +swap_min_sigterm_swap = sig_level_to_kb_swap(swap_min_sigterm) +swap_min_sigkill_swap = sig_level_to_kb_swap(swap_min_sigkill) + +if type(swap_min_sigterm_swap) is tuple: + swap_term_is_percent = True + swap_min_sigterm_percent = swap_min_sigterm_swap[0] +else: + swap_term_is_percent = False + swap_min_sigterm_kb = swap_min_sigterm_swap + +if type(swap_min_sigkill_swap) is tuple: + swap_kill_is_percent = True + swap_min_sigkill_percent = swap_min_sigkill_swap[0] +else: + swap_kill_is_percent = False + swap_min_sigkill_kb = swap_min_sigkill_swap + + +# print('\nswap term is percent:', swap_term_is_percent) +# print('swap kill is percent:', swap_kill_is_percent) + + + + print("\ncurrent process's effective user id", os.geteuid()) if os.geteuid() == 0: @@ -408,6 +423,8 @@ except OSError: +def kib_to_mib(num): + return round(num / 1024.0) ########################################################################################### @@ -430,8 +447,15 @@ while True: swap_free = int(line.split(':')[1].split(' ')[-2]) break + if swap_kill_is_percent: + swap_min_sigkill_kb = swap_total * swap_min_sigkill_percent / 100.0 - # тут находим фулл зрам + if swap_term_is_percent: + swap_min_sigterm_kb = swap_total * swap_min_sigterm_percent / 100.0 + + + + # находим MemUsedZram disksize_sum = 0 mem_used_total_sum = 0 @@ -444,67 +468,90 @@ while True: disksize_sum += int(stat[0]) mem_used_total_sum += int(stat[1]) - full_zram = ( + mem_used_zram = ( mem_used_total_sum + disksize_sum * zram_disksize_factor ) / 1024.0 - # если не печатать периоды, то можно это вынести в конец - t_mem = mem_available / 1024.0 / 1024.0 / rate_mem - t_swap = swap_free / 1024.0 / 1024.0 / rate_swap - # fullzram может превысить 09, будет отриц значение - # memtotal * 0.9 - это фактически макс память для зрам - t_zram = (mem_total * 0.8 - full_zram) / 1024.0 / 1024.0 / rate_zram - if t_zram <= 0: + t_mem = mem_available / 1000000.0 / rate_mem + t_swap = swap_free / 10000000.0 / rate_swap + t_zram = (mem_total * 0.8 - mem_used_zram) / 1000000.0 / rate_zram + if t_zram < 0.01: t_zram = 0.01 - t1 = t_mem + t_swap - t2 = t_mem + t_zram + t_mem_swap = t_mem + t_swap + t_mem_zram = t_mem + t_zram - # используем наименьший - if t1 <= t2: - t = t1 + if t_mem_swap <= t_mem_zram: + t = t_mem_swap else: - t = t2 + t = t_mem_zram + # печать состояния памяти print( - '{} Mem: {} M, Swap: {} M, Zram: {} M'.format( - strftime("%Y-%b-%d %H:%M:%S", gmtime()), + 'MemAvail: {}M {}%, SwapFree: {}M {}%, MemUsedZram: {}M {}%'.format( human(mem_available), + to_percent(mem_available / mem_total), human(swap_free), - human(full_zram) + to_percent(swap_free / (swap_total + 0.0001)), + human(mem_used_zram), + to_percent(mem_used_zram / mem_total) ) ) + # MEM SWAP KILL if mem_available <= mem_min_sigkill_kb and swap_free <= swap_min_sigkill_kb: - print('mem_available < mem_min_sigkill and swap_free < swap_min_sigkill') + 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) + ) + ) find_victim(SIGKILL) sleep(min_delay_after_sigkill) continue - if full_zram >= zram_max_sigkill_kb: - print('full_zram > zram_max_sigkill') + # 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) + ) + ) find_victim(SIGKILL) sleep(min_delay_after_sigkill) continue + # MEM SWAP TERM if mem_available <= mem_min_sigterm_kb and swap_free <= swap_min_sigterm_kb: - print('mem_available < mem_min_sigterm and swap_free < swap_min_sigterm') + 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) + ) + ) find_victim(SIGTERM) sleep(min_delay_after_sigterm) - if full_zram >= zram_max_sigterm_kb: - print('zram_part > zram_max_sigterm') + # 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) + ) + ) find_victim(SIGTERM) sleep(min_delay_after_sigterm) - # вариант - перенести задержку в фц поиска жертв sleep(t) - - - diff --git a/nohang.1 b/nohang.1 index 0c2bb25..9d4ea95 100644 --- a/nohang.1 +++ b/nohang.1 @@ -2,11 +2,21 @@ .SH NAME nohang \- no hang daemon - .SH SYNOPSIS .B nohang .RB [ OPTION ]... - .SH DESCRIPTION -See https://github.com/hakavlad/nohang +Nohang - аналог earlyoom с поддержкой zram и SIGTERM. При дефиците доступной памяти nohang корректно завершает наиболее прожорливые процессы сигналом SIGTERM, тем самым препятствуя зависанию, а также избыточному убийству процессов ядерным OOM killer'ом. See https://github.com/hakavlad/nohang + +.SH OPTIONS +.TP +.BI \-c " CONFIG", +.BI \-\-config " CONFIG" +path to config file, default values: +.I ./nohang.conf, +.I /etc/nohang/nohang.conf +.TP +.BI \-h, +.BI \-\-help +show help message and exit diff --git a/nohang.conf b/nohang.conf index e25424f..5e3e973 100644 --- a/nohang.conf +++ b/nohang.conf @@ -36,6 +36,16 @@ self_oom_score_adj = -1000 Уменьшение коэффициентов способно снизить нагрузку на прцессор и увеличить периоды между проверками памяти. + Почему три коэффициента, а не один? - Потому что + скорость наполнения свопа обычно ниже скорости наполнения RAM. + Можно для свопа задать более низкую интенсивность + мониторинга без ущерба для предотвращения нехватки памяти + и тем самым снизить нагрузку на процессор. + + В дефолтных настройках на данной интенсивности демон работает + очень хорошо, перехватывая резкие скачки потребления памяти. + Можете тестировать + rate_mem = 6 rate_swap = 2 rate_zram = 1 @@ -44,10 +54,16 @@ rate_zram = 1 Задание уровней доступной памяти, ниже которых происходит отправка сигналов SIGTERM или SIGKILL. + Сигнал отправляется если MemAvailable и SwapFree одновременно опустятся ниже соответствующих значений. + Значения могут быть выражены в процентах (%), - кибибайтах (KiB), мебибайтах (MiB) или гибибайтах (GiB). + кибибайтах (K), мебибайтах (M) или гибибайтах (G). + Например: + swap_min_sigterm = 8 % + mem_min_sigterm = 0.5 G + swap_min_sigkill = 200 M mem_min_sigterm = 6 % mem_min_sigkill = 3 % @@ -60,7 +76,7 @@ swap_min_sigkill = 4 % система виснет или запускается OOM killer. По мере увеличения доли zram в памяти может падать отзывчивость системы. - Может также задаваться в %, KiB, MiB, GiB + Может также задаваться в %, K, M, G zram_max_sigterm = 60 % zram_max_sigkill = 65 % @@ -100,6 +116,11 @@ decrease_oom_score_adj_enable = no oom_score_adj_before = 50 oom_score_adj_after = 10 + +##################################################################### +##################################################################### +##################################################################### +##################################################################### ##################################################################### Значения по умолчанию @@ -124,7 +145,7 @@ oom_score_adj_after = 10 min_delay_after_sigterm = 0.1 min_delay_after_sigkill = 3 - decrease_oom_score_adj_enable = yes + decrease_oom_score_adj_enable = no oom_score_adj_before = 50 oom_score_adj_after = 10 diff --git a/purge.sh b/purge.sh index 72a774a..a57e6cc 100755 --- a/purge.sh +++ b/purge.sh @@ -1,7 +1,7 @@ #!/bin/bash -v systemctl stop nohang systemctl disable nohang -rm /usr/local/share/man/man1/nohang.1.gz -rm /etc/systemd/system/nohang.service -rm -r /etc/nohang -rm /usr/local/bin/nohang +rm -f /usr/local/share/man/man1/nohang.1.gz +rm -f /etc/systemd/system/nohang.service +rm -rf /etc/nohang +rm -f /usr/local/bin/nohang diff --git a/uninstall.sh b/uninstall.sh index 36dbb57..b7914d5 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,6 +1,6 @@ #!/bin/bash -v systemctl stop nohang systemctl disable nohang -rm /usr/local/share/man/man1/nohang.1.gz -rm /etc/systemd/system/nohang.service -rm /usr/local/bin/nohang +rm -f /usr/local/share/man/man1/nohang.1.gz +rm -f /etc/systemd/system/nohang.service +rm -f /usr/local/bin/nohang