drop-out logging, blacklist and whitelist support, add realtime_ionice support

This commit is contained in:
Alexey Avramov 2018-07-11 04:30:27 +09:00
parent a96eeb8ad2
commit b910bf1b28
7 changed files with 201 additions and 342 deletions

View File

@ -15,12 +15,12 @@ OOM killer doesn't prevent OOM conditions.
### Some features ### Some features
- convenient configuration with a well commented config file (there are 38 parameters in the config) - convenient configuration with a well commented config file (there are 35 parameters in the config)
- `SIGKILL` and `SIGTERM` as signals that can be sent to the victim - `SIGKILL` and `SIGTERM` as signals that can be sent to the victim
- `zram` support (`mem_used_total` as a trigger) - `zram` support (`mem_used_total` as a trigger)
- customizable intensity of monitoring - customizable intensity of monitoring
- desktop notifications: results of preventings OOM and low memory warnings - desktop notifications: results of preventings OOM and low memory warnings
- black, white, prefer, avoid lists via regex - prefer and avoid lists via regex matching
- possibility of restarting processes via command like `systemctl restart something` if the process is selected as a victim - possibility of restarting processes via command like `systemctl restart something` if the process is selected as a victim
- look at the [config](https://github.com/hakavlad/nohang/blob/master/nohang.conf) to find more - look at the [config](https://github.com/hakavlad/nohang/blob/master/nohang.conf) to find more
@ -32,34 +32,11 @@ OOM killer doesn't prevent OOM conditions.
### An example of output ### An example of output
``` ```
MemAvail: 2976 M, 50.6 % | SwapFree: 10758 M, 100.0 %
MemAvail: 0 M, 0.0 % | SwapFree: 10281 M, 95.6 %
MemAvail: 0 M, 0.0 % | SwapFree: 9918 M, 92.2 %
MemAvail: 0 M, 0.0 % | SwapFree: 8659 M, 80.5 %
MemAvail: 0 M, 0.0 % | SwapFree: 7235 M, 67.3 %
MemAvail: 19 M, 0.3 % | SwapFree: 6851 M, 63.7 %
MemAvail: 0 M, 0.0 % | SwapFree: 5780 M, 53.7 %
MemAvail: 0 M, 0.0 % | SwapFree: 5008 M, 46.6 %
MemAvail: 0 M, 0.0 % | SwapFree: 4199 M, 39.0 %
MemAvail: 0 M, 0.0 % | SwapFree: 3502 M, 32.6 %
MemAvail: 0 M, 0.0 % | SwapFree: 2929 M, 27.2 %
MemAvail: 0 M, 0.0 % | SwapFree: 2446 M, 22.7 %
MemAvail: 0 M, 0.0 % | SwapFree: 2093 M, 19.5 %
MemAvail: 0 M, 0.0 % | SwapFree: 1573 M, 14.6 %
MemAvail: 0 M, 0.0 % | SwapFree: 1320 M, 12.3 %
MemAvail: 0 M, 0.0 % | SwapFree: 1117 M, 10.4 %
MemAvail: 0 M, 0.0 % | SwapFree: 943 M, 8.8 %
2018-07-06 Fri 03:04:37
MemAvailable (0 MiB, 0.0 %) < mem_min_sigterm (588 MiB, 10.0 %) MemAvailable (0 MiB, 0.0 %) < mem_min_sigterm (588 MiB, 10.0 %)
SwapFree (943 MiB, 8.8 %) < swap_min_sigterm (1076 MiB, 10.0 %) SwapFree (943 MiB, 8.8 %) < swap_min_sigterm (1076 MiB, 10.0 %)
Preventing OOM: trying to send the SIGTERM signal to tail, Preventing OOM: trying to send the SIGTERM signal to tail,
Pid: 14636, Badness: 777, VmRSS: 4446 MiB, VmSwap: 8510 MiB Pid: 14636, Badness: 777, VmRSS: 4446 MiB, VmSwap: 8510 MiB
Success Success
MemAvail: 173 M, 2.9 % | SwapFree: 3363 M, 31.3 %
MemAvail: 4700 M, 80.0 % | SwapFree: 8986 M, 83.5 %
MemAvail: 4668 M, 79.4 % | SwapFree: 8997 M, 83.6 %
MemAvail: 4610 M, 78.5 % | SwapFree: 9024 M, 83.9 %
``` ```
### Requirements ### Requirements
@ -117,11 +94,10 @@ The program can be configured by editing the [config file](https://github.com/ha
- PREVENTION OF KILLING INNOCENT VICTIMS - PREVENTION OF KILLING INNOCENT VICTIMS
- AVOID AND PREFER VICTIM NAMES VIA REGEX - AVOID AND PREFER VICTIM NAMES VIA REGEX
- EXECUTE THE COMMAND INSTEAD OF SENDING THE SIGTERM SIGNAL - EXECUTE THE COMMAND INSTEAD OF SENDING THE SIGTERM SIGNAL
- DESKTOP NOTIFICATIONS - GUI NOTIFICATIONS
- LOW MEMORY WARNINGS - LOW MEMORY WARNINGS
- SELF-DEFENSE - SELF-DEFENSE AND PREVENTING SLOWING DOWN THE PROGRAM
- OUTPUT VERBOSITY - OUTPUT VERBOSITY
- LOGGING TO SEPARATE FILE
Just read the description of the parameters and edit the values. Run the command `sudo systemctl restart nohang` to apply changes. Default path to the config arter installing via `./install.sh` is `/etc/nohang/nohang.conf`. Just read the description of the parameters and edit the values. Run the command `sudo systemctl restart nohang` to apply changes. Default path to the config arter installing via `./install.sh` is `/etc/nohang/nohang.conf`.

View File

@ -15,12 +15,6 @@ cp nohang.1.gz /usr/local/share/man/man1/
chmod 644 /usr/local/share/man/man1/nohang.1.gz chmod 644 /usr/local/share/man/man1/nohang.1.gz
rm nohang.1.gz rm nohang.1.gz
mkdir /var/log/nohang
chmod 750 /var/log/nohang
cp nohang.logrotate /etc/logrotate.d/nohang
chmod 644 /etc/logrotate.d/nohang
cp nohang.service /etc/systemd/system/ cp nohang.service /etc/systemd/system/
chmod 644 /etc/systemd/system/nohang.service chmod 644 /etc/systemd/system/nohang.service
systemctl daemon-reload systemctl daemon-reload

156
nohang
View File

@ -5,8 +5,8 @@
import os import os
from operator import itemgetter from operator import itemgetter
from time import sleep, time from time import sleep, time
import datetime
from argparse import ArgumentParser from argparse import ArgumentParser
from subprocess import Popen
sig_dict = {9: 'SIGKILL', 15: 'SIGTERM'} sig_dict = {9: 'SIGKILL', 15: 'SIGTERM'}
@ -110,20 +110,6 @@ def write(path, string):
f.write(string) f.write(string)
def append_log(string):
try:
with open(logfile, 'a') as f:
f.write(string + '\n')
except PermissionError:
print(
' Cannot append log {}: PermissionError'.format(
logfile))
except IsADirectoryError:
print(
' Cannot append log {}: IsADirectoryError'.format(
logfile))
def kib_to_mib(num): def kib_to_mib(num):
return round(num / 1024.0) return round(num / 1024.0)
@ -228,25 +214,6 @@ def send_notify(signal, name, pid, oom_score, vm_rss, vm_swap):
os.system(user_notify_command + info) os.system(user_notify_command + info)
def send_notify_black(signal, name, pid):
# текст отправляемого уведомления
info = '"<u>Nohang</u> sent <u>{}</u>\nto blacklisted proce' \
'ss <b>{}</b>, <i>Pid</i> <b>{}</b>" &'.format(
sig_dict[signal], name, pid)
if root:
# отправляем уведомление всем залогиненным пользователям
for uid in os.listdir('/run/user'):
root_notify_command = 'sudo -u {} DISPLAY={} notify-send {} "Pr' \
'eventing OOM" '.format(
users_dict[uid], root_display, notify_options)
os.system(root_notify_command + info)
else:
# отправляем уведомление пользователю, который запустил nohang
user_notify_command = 'notify-send {} "Preventing OOM" '.format(
notify_options)
os.system(user_notify_command + info)
def sleep_after_send_signal(signal): def sleep_after_send_signal(signal):
if signal is 9: if signal is 9:
if print_sleep_periods: if print_sleep_periods:
@ -260,6 +227,9 @@ def sleep_after_send_signal(signal):
def find_victim_and_send_signal(signal): def find_victim_and_send_signal(signal):
print('****')
print(mem_info)
# выставляем потолок для oom_score_adj всех процессов # выставляем потолок для oom_score_adj всех процессов
if decrease_oom_score_adj and root: if decrease_oom_score_adj and root:
func_decrease_oom_score_adj(oom_score_adj_max) func_decrease_oom_score_adj(oom_score_adj_max)
@ -269,9 +239,6 @@ def find_victim_and_send_signal(signal):
if use_regex_lists: if use_regex_lists:
# pid list, rename var! blacklisted_pids
oom_blacklist_regex = []
for pid in os.listdir('/proc'): for pid in os.listdir('/proc'):
if pid.isdigit() is not True: if pid.isdigit() is not True:
continue continue
@ -280,20 +247,6 @@ def find_victim_and_send_signal(signal):
oom_score = int(rline1('/proc/' + pid + '/oom_score')) oom_score = int(rline1('/proc/' + pid + '/oom_score'))
name = pid_to_name(pid) name = pid_to_name(pid)
# если имя в белом списке,то пропускаем
res = fullmatch(whitelist_regex, name)
if res is not None:
print(' {} (Pid: {}) matches with whitelist_regex'.format(name, pid)),
continue
# если имя в черном списке - добавляем Pid в список для убийства
# ДОБАВЛЯТЬ И ИМЯ СРАЗУ
# ВАРИАНТ - СРАЗУ УБИВАТЬ
res = fullmatch(blacklist_regex, name)
if res is not None:
oom_blacklist_regex.append(pid)
print(' {} (Pid: {}) matches with blacklist_regex'.format(name, pid)),
res = fullmatch(avoidlist_regex, name) res = fullmatch(avoidlist_regex, name)
if res is not None: if res is not None:
# тут уже получаем badness # тут уже получаем badness
@ -311,35 +264,6 @@ def find_victim_and_send_signal(signal):
oom_score = 0 oom_score = 0
oom_list.append((pid, oom_score)) oom_list.append((pid, oom_score))
# если найден хоть один в черном списке - нет смысла сравнивать с остальными
if oom_blacklist_regex != []:
for pid in oom_blacklist_regex:
name = pid_to_name(pid)
print(' Preventing OOM: trying to send the {} signal to blacklisted process {}, Pid: {}'.format(
sig_dict[signal], name, pid))
try:
os.kill(int(pid), signal)
print(' Success')
if desktop_notifications:
send_notify_black(signal, name, pid)
except FileNotFoundError:
print(' No such process')
except ProcessLookupError:
print(' No such process')
except PermissionError:
print(' Operation not permitted')
# после отправки сигнала процессам из черного списка поспать и выйти из функции
sleep_after_send_signal(signal)
return 0
else: else:
# not use regex # not use regex
@ -354,14 +278,12 @@ def find_victim_and_send_signal(signal):
oom_score = 0 oom_score = 0
oom_list.append((i, oom_score)) oom_list.append((i, oom_score))
# получаем отсортированный по oom_score (по badness!) список пар (pid, oom_score) # получаем отсортированный по oom_score (по badness!) список пар (pid, oom_score)
pid_tuple_list = sorted(oom_list, key=itemgetter(1), reverse=True)[0] pid_tuple_list = sorted(oom_list, key=itemgetter(1), reverse=True)[0]
# получаем максимальный oom_score # получаем максимальный oom_score
oom_score = pid_tuple_list[1] oom_score = pid_tuple_list[1]
if oom_score >= oom_score_min: if oom_score >= oom_score_min:
# пытаемся отправить сигнал найденной жертве # пытаемся отправить сигнал найденной жертве
@ -392,13 +314,12 @@ def find_victim_and_send_signal(signal):
vm_rss = 0 vm_rss = 0
vm_swap = 0 vm_swap = 0
if name in etc_dict and signal is 15: if name in etc_dict and signal is 15:
command = etc_dict[name] command = etc_dict[name]
etc_info = ' Process {} is a victim,\n Pid: {}, Badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Execute command: {}'.format(name, pid, oom_score, vm_rss, vm_swap, command) etc_info = ' Process {} is a victim,\n Pid: {}, Badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Execute command: {}'.format(name, pid, oom_score, vm_rss, vm_swap, command)
os.system(etc_dict[name]) # все норм, это произвольная команда задана юзером
print(etc_info) print(etc_info)
os.system(etc_dict[name]) # еще ГУИ уведомление запустить
append_log(etc_info)
else: else:
@ -414,25 +335,11 @@ def find_victim_and_send_signal(signal):
except ProcessLookupError: except ProcessLookupError:
send_result = ' No such process' send_result = ' No such process'
time_now_and_mem_info = datetime.datetime.today().strftime(
'\n%Y-%m-%d %a %H:%M:%S\n{}'.format(mem_info))
print(time_now_and_mem_info)
if logging:
append_log(time_now_and_mem_info)
try_to_send = ' Preventing OOM: trying to send the {} signal to {},\n Pid: {}, Badness: {}, VmRSS: {} MiB, VmSwap: {} MiB'.format(sig_dict[signal], name, pid, oom_score, vm_rss, vm_swap) try_to_send = ' Preventing OOM: trying to send the {} signal to {},\n Pid: {}, Badness: {}, VmRSS: {} MiB, VmSwap: {} MiB'.format(sig_dict[signal], name, pid, oom_score, vm_rss, vm_swap)
print(try_to_send) print(try_to_send)
print(send_result) print(send_result)
if logging:
append_log(try_to_send + '\n' + send_result)
else: else:
badness_is_too_small = ' oom_score {} < oom_score_min {}'.format( badness_is_too_small = ' oom_score {} < oom_score_min {}'.format(
@ -440,9 +347,6 @@ def find_victim_and_send_signal(signal):
print(badness_is_too_small) print(badness_is_too_small)
if logging:
append_log(badness_is_too_small)
sleep_after_send_signal(signal) sleep_after_send_signal(signal)
@ -611,6 +515,23 @@ print_mem_check_results = conf_parse_bool('print_mem_check_results')
print_sleep_periods = conf_parse_bool('print_sleep_periods') print_sleep_periods = conf_parse_bool('print_sleep_periods')
realtime_ionice = conf_parse_bool('realtime_ionice')
if 'realtime_ionice_classdata' in config_dict:
realtime_ionice_classdata = string_to_int_convert_test(
config_dict['realtime_ionice_classdata'])
if realtime_ionice_classdata is None:
print('Invalid realtime_ionice_classdata value, not integer\nExit')
exit()
if realtime_ionice_classdata < 0 or realtime_ionice_classdata > 7:
print('Invalid realtime_ionice_classdata value\nExit')
exit()
else:
print('realtime_ionice_classdata not in config\nExit')
exit()
mlockall = conf_parse_bool('mlockall') mlockall = conf_parse_bool('mlockall')
@ -952,12 +873,6 @@ if use_regex_lists:
from re import fullmatch from re import fullmatch
whitelist_regex = conf_parse_string('whitelist_regex')
blacklist_regex = conf_parse_string('blacklist_regex')
preferlist_regex = conf_parse_string('preferlist_regex') preferlist_regex = conf_parse_string('preferlist_regex')
@ -990,11 +905,8 @@ else:
exit() exit()
logging = conf_parse_bool('logging')
logfile = conf_parse_string('logfile')
low_memory_warnings = conf_parse_bool('low_memory_warnings') low_memory_warnings = conf_parse_bool('low_memory_warnings')
@ -1190,7 +1102,11 @@ else:
mla_res = '' mla_res = ''
if os.geteuid() == 0: self_uid = os.geteuid()
self_pid = os.getpid()
if self_uid == 0:
root = True root = True
decrease_res = 'OK' decrease_res = 'OK'
else: else:
@ -1198,6 +1114,15 @@ else:
decrease_res = 'Impossible' decrease_res = 'Impossible'
if root and realtime_ionice:
os.system('ionice -c 1 -n {} -p {}'.format(
realtime_ionice_classdata ,self_pid))
print('\nionice:'.format())
os.system('ionice')
print()
########################################################################## ##########################################################################
@ -1258,18 +1183,11 @@ if print_config:
print('\nVII. AVOID AND PREFER VICTIM NAMES VIA REGEX') print('\nVII. AVOID AND PREFER VICTIM NAMES VIA REGEX')
print('use_regex_lists: {}'.format(use_regex_lists)) print('use_regex_lists: {}'.format(use_regex_lists))
if use_regex_lists: if use_regex_lists:
print('whitelist_regex: {}'.format(whitelist_regex))
print('blacklist_regex: {}'.format(blacklist_regex))
print('preferlist_regex: {}'.format(preferlist_regex)) print('preferlist_regex: {}'.format(preferlist_regex))
print('preferlist_factor: {}'.format(preferlist_factor)) print('preferlist_factor: {}'.format(preferlist_factor))
print('avoidlist_regex: {}'.format(avoidlist_regex)) print('avoidlist_regex: {}'.format(avoidlist_regex))
print('avoidlist_factor: {}'.format(avoidlist_factor)) print('avoidlist_factor: {}'.format(avoidlist_factor))
print('\nVIII. LOGGING')
print('logging: {}'.format(logging))
if logging:
print('logfile: {}'.format(logfile))
print('\nIX. LOW MEMORY WARNINGS') print('\nIX. LOW MEMORY WARNINGS')
print('low_memory_warnings: {}'.format(low_memory_warnings)) print('low_memory_warnings: {}'.format(low_memory_warnings))
if low_memory_warnings: if low_memory_warnings:

View File

@ -5,98 +5,22 @@
The configuration includes the following sections: The configuration includes the following sections:
I. STANDARD OUTPUT VERBOSITY * THRESHOLDS FOR SENDING SIGNALS
II. SELF-DEFENSE * INTENSITY OF MONITORING (AND CPU USAGE)
III. INTENSITY OF MONITORING * PREVENTION OF KILLING INNOCENT VICTIMS
IV. THRESHOLDS FOR SENDING SIGNALS * AVOID AND PREFER VICTIM NAMES VIA REGEX
V. PREVENTION OF KILLING INNOCENT VICTIMS * EXECUTE THE COMMAND INSTEAD OF SENDING THE SIGTERM SIGNAL
VI. DESKTOP NOTIFICATIONS * GUI NOTIFICATIONS
VII. AVOID AND PREFER VICTIM NAMES VIA REGEX * LOW MEMORY WARNINGS
VIII. LOGGING * SELF-DEFENSE AND PREVENTING SLOWING DOWN THE PROGRAM
IX. LOW MEMORY WARNINGS * OUTPUT VERBOSITY
X. EXECUTE THE COMMAND INSTEAD OF SENDING THE SIGTERM SIGNAL
Just read the description of the parameters and edit the values. Just read the description of the parameters and edit the values.
Please restart the program after editing the config. Please restart the program after editing the config.
##################################################################### #####################################################################
I. STANDARD OUTPUT VERBOSITY I. THRESHOLDS FOR SENDING SIGNALS
Display the configuration when the program starts.
Valid values are True and False.
Values are case sensitive!
print_config = True
Print memory check results or not print.
Valid values are True and False.
print_mem_check_results = True
Print sleep periods between memory checks or not print.
Valid values are True and False.
print_sleep_periods = False
#####################################################################
II. SELF-DEFENSE
True - заблокировать процесс в памяти для запрета его своппинга.
False - не блокировать. Значения чувствительны к регистру!
В Fedora 28 значение True вызывает увеличение потребления
памяти процессом на 200 MiB, в Debian 8 и 9 такой проблемы нет.
mlockall = False
Установка отрицательных значений self_nice и self_oom_score_adj
требует наличия root прав.
Установка отрицательного self_nice повышает приоритет процесса.
Valid values are integers from the range [-20; 19].
self_nice = -10
Set oom_score_adj for the process.
Valid values are integers from the range [-1000; 1000].
Setting the values to -1000 will prohibit suicide.
self_oom_score_adj = -100
#####################################################################
III. INTENSITY OF MONITORING
Coefficients that affect the intensity of monitoring. Reducing
the coefficients can reduce CPU usage and increase the periods
between memory checks.
Почему три коэффициента, а не один? - Потому что скорость
наполнения свопа обычно ниже скорости наполнения RAM.
Можно для свопа задать более низкую интенсивность
мониторинга без ущерба для предотвращения нехватки памяти
и тем самым снизить нагрузку на процессор.
В дефолтных настройках на данной интенсивности демон работает
достаточно хорошо, успешно справляясь с резкими скачками потребления
памяти.
Default values are well for desktop.
On servers without rapid fluctuations in memory level, the
values can be reduced.
Valid values are positive floating-point numbers.
rate_mem = 6
rate_swap = 3
rate_zram = 1
#####################################################################
IV. THRESHOLDS FOR SENDING SIGNALS
Sets the available memory levels below which SIGTERM or SIGKILL Sets the available memory levels below which SIGTERM or SIGKILL
signals are sent. The signal will be sent if MemAvailable and signals are sent. The signal will be sent if MemAvailable and
@ -123,7 +47,35 @@ zram_max_sigkill = 60 %
##################################################################### #####################################################################
V. PREVENTION OF KILLING INNOCENT VICTIMS II. INTENSITY OF MONITORING
Coefficients that affect the intensity of monitoring. Reducing
the coefficients can reduce CPU usage and increase the periods
between memory checks.
Почему три коэффициента, а не один? - Потому что скорость
наполнения свопа обычно ниже скорости наполнения RAM.
Можно для свопа задать более низкую интенсивность
мониторинга без ущерба для предотвращения нехватки памяти
и тем самым снизить нагрузку на процессор.
В дефолтных настройках на данной интенсивности демон работает
достаточно хорошо, успешно справляясь с резкими скачками потребления
памяти.
Default values are well for desktop.
On servers without rapid fluctuations in memory level, the
values can be reduced.
Valid values are positive floating-point numbers.
rate_mem = 4
rate_swap = 2
rate_zram = 1
#####################################################################
III. PREVENTION OF KILLING INNOCENT VICTIMS
Минимальное значение oom_score, которым должен обладать Минимальное значение oom_score, которым должен обладать
процесс для того, чтобы ему был отправлен сигнал. процесс для того, чтобы ему был отправлен сигнал.
@ -162,7 +114,73 @@ oom_score_adj_max = 20
##################################################################### #####################################################################
VI. DESKTOP NOTIFICATIONS IV. AVOID AND PREFER VICTIM NAMES VIA REGEX
Можно задать регулярные выражения (Perl-compatible regular
expressions), которые будут использоваться для сопоставления с
именами процессов для влияния на их badness.
Включение этой опции замедляет поиск жертвы, так как
имена всех процессов сравниваются с заданными regex-паттернами.
Valid values are True and False.
use_regex_lists = False
Badness процессов, имена которых соответствуют preferlist_regex,
будут рассчитываться по формуле
badness = (oom_score + 1) * preferlist_factor
preferlist_regex = tail|python3
Valid values are floating-point numbers from the range [1; 1000].
preferlist_factor = 3
Список нежелательных для убийства процессов.
Badness процессов, имена которых соответствуют avoidlist_regex,
будут рассчитываться по формуле
badness = oom_score / avoidlist_factor
avoidlist_regex = Xorg|sshd
Valid values are floating-point numbers from the range [1; 1000].
avoidlist_factor = 4
#####################################################################
V. EXECUTE THE COMMAND INSTEAD OF SENDING THE SIGTERM SIGNAL
Для процессов с определенным именем можно задать команду,
которая будет выполняться вместо отправки сигнала SIGTERM
процессу с соответствующим именем.
Например, если процесс запущен как демон, то вместо
отправки SIGTERM можно выполнить команду перезапуска.
Valid values are True and False.
execute_the_command = False
Длина имени процесса не должна превышать 15 символов.
Синтаксис таков: строки, начинающиеся с **, считаются строками,
содержащими имена процессов и соотвестствующие команды для
перезапуска этих процессов. После имени процесса через двойное
двоеточие (::) следует команда.
Амперсанд (&) в конце команды позволит nohang продолжить работу
не дожидаясь окончания выполнения команды.
For example:
** mysqld :: systemctl restart mariadb.service &
** php-fpm7.0 :: systemctl restart php7.0-fpm.service &
** processname :: some command
#####################################################################
VI. GUI NOTIFICATIONS
Включение этой опции требует наличия notify-send в системе. Включение этой опции требует наличия notify-send в системе.
В Debian/Ubuntu это обеспечивается установкой пакета В Debian/Ubuntu это обеспечивается установкой пакета
@ -192,79 +210,11 @@ root_display = :0
##################################################################### #####################################################################
VII. AVOID AND PREFER VICTIM NAMES VIA REGEX VII. LOW MEMORY WARNINGS
Можно задать регулярные выражения (Perl-compatible regular
expressions), которые будут использоваться для сопоставления с
именами процессов для влияния на их badness.
Включение этой опции замедляет поиск жертвы, так как
имена всех процессов сравниваются с заданными regex-паттернами.
Valid values are True and False.
use_regex_lists = False
Приоритет списков (если один процесс находится одновременно в
нескольких):
1. whitelist_regex: сначала пропуск процессов из белого списка;
2. blacklist_regex: отправка сигнала всем из черного списка;
3. preferlist_regex и avoidlist_regex: умножение или деление
oom_score на соответствующие факторы.
Процессы, имена которых соответствуют выражению
whitelist_regex, не получат сигнал.
Регулярное выражение для формирования белого списка.
whitelist_regex = sshd
При нехватке памяти все процессы, имена которых соответствуют
blacklist_regex, получат сигнал.
blacklist_regex =
Badness процессов, имена которых соответствуют preferlist_regex,
будут рассчитываться по формуле
badness = (oom_score + 1) * preferlist_factor
preferlist_regex = tail|python3|someprocessname
Valid values are floating-point numbers from the range [1; 1000].
preferlist_factor = 3
Список нежелательных для убийства процессов.
Badness процессов, имена которых соответствуют avoidlist_regex,
будут рассчитываться по формуле
badness = oom_score / avoidlist_factor
avoidlist_regex = Xorg
Valid values are floating-point numbers from the range [1; 1000].
avoidlist_factor = 3
#####################################################################
VIII. LOGGING
OOM prevention progress can be logged.
Valid values are True and False.
logging = True
logfile = /var/log/nohang/nohang.log
#####################################################################
IX. LOW MEMORY WARNINGS
Десктопные уведомления о низком уровне доступной памяти. Десктопные уведомления о низком уровне доступной памяти.
Для работы опции должны быть включены десктопные уведомления. Для работы опции должны быть включены десктопные уведомления.
Возможно стоит этот раздел объединить с DESKTOP NOTIFICATIONS. Возможно стоит этот раздел объединить с GUI NOTIFICATIONS.
Valid values are True and False. Valid values are True and False.
@ -293,30 +243,62 @@ zram_max_warnings = 40 %
##################################################################### #####################################################################
X. EXECUTE THE COMMAND INSTEAD OF SENDING THE SIGTERM SIGNAL VIII. SELF-DEFENSE AND PREVENTING SLOWING DOWN THE PROGRAM
Для процессов с определенным именем можно задать команду, True - заблокировать процесс в памяти для запрета его своппинга.
которая будет выполняться вместо отправки сигнала SIGTERM False - не блокировать.
процессу с соответствующим именем.
Например, если процесс запущен как демон, то вместо В Fedora 28 значение True вызывает увеличение потребления
отправки SIGTERM можно выполнить команду перезапуска. памяти процессом на 200 MiB, в Debian 8 и 9 такой проблемы нет.
mlockall = False
Установка отрицательных значений self_nice и self_oom_score_adj
требует наличия root прав.
Установка отрицательного self_nice повышает приоритет процесса.
Valid values are integers from the range [-20; 19].
self_nice = -15
# -> niceness
Set oom_score_adj for the process.
Valid values are integers from the range [-1000; 1000].
Setting the values to -1000 will prohibit suicide.
self_oom_score_adj = -100
Read `man ionice` to understand the following parameters.
Setting the True value requires the root privileges.
realtime_ionice = True
'For realtime and best-effort, 0-7 are valid data
(priority levels), and 0 represents the highest priority level.'
- `man ionice`
Valid values are integers from the range [0; 7].
realtime_ionice_classdata = 5
#####################################################################
IX. STANDARD OUTPUT VERBOSITY
Display the configuration when the program starts.
Valid values are True and False.
Values are case sensitive!
print_config = False
Print memory check results or not print.
Valid values are True and False. Valid values are True and False.
execute_the_command = False print_mem_check_results = False
Длина имени процесса не должна превышать 15 символов. Print sleep periods between memory checks or not print.
Синтаксис таков: строки, начинающиеся с **, считаются строками, Valid values are True and False.
содержащими имена процессов и соотвестствующие команды для
перезапуска этих процессов. После имени процесса через двойное
двоеточие (::) следует команда.
Амперсанд (&) в конце команды позволит nohang продолжить работу
не дожидаясь окончания выполнения команды.
For example: print_sleep_periods = False
** mysqld :: systemctl restart mariadb.service &
** php-fpm7.0 :: systemctl restart php7.0-fpm.service &
** processname :: some command

View File

@ -1,9 +0,0 @@
/var/log/nohang/*.log {
create 640 root adm
missingok
notifempty
weekly
rotate 5
compress
delaycompress
}

View File

@ -7,7 +7,7 @@ Documentation=man:nohang(1) https://github.com/hakavlad/nohang
[Service] [Service]
Type=simple Type=simple
Restart=always Restart=always
StandardOutput=null StandardOutput=syslog
StandardError=syslog StandardError=syslog
ExecStart=/usr/local/bin/nohang ExecStart=/usr/local/bin/nohang

View File

@ -4,6 +4,4 @@ systemctl disable nohang
rm /usr/local/bin/nohang rm /usr/local/bin/nohang
rm /usr/local/share/man/man1/nohang.1.gz rm /usr/local/share/man/man1/nohang.1.gz
rm /etc/systemd/system/nohang.service rm /etc/systemd/system/nohang.service
rm /etc/logrotate.d/nohang
rm -r /etc/nohang rm -r /etc/nohang
rm -r /var/log/nohang