обеспечена поддержка десктопных уведомлений
This commit is contained in:
parent
b0805dc450
commit
696eae2dc7
@ -34,7 +34,7 @@ https://2ch.hk/s/res/2310304.html#2311483, https://archive.li/idixk
|
||||
|
||||
### Некоторые особенности
|
||||
- задача - препятствовать зависанию системы при нехватке доступной памяти, а также корректное завершение процессов с целью увеличения объема доступной памяти
|
||||
- демон на Python 3, VmRSS не более 13 MiB
|
||||
- демон на Python 3, VmRSS от 10 до 14 MiB в зависимости от настроек
|
||||
- требуется ядро `Linux 3.14` или новее
|
||||
- периодически проверяет объем доступной памяти, при дефиците памяти отправляет `SIGKILL` или `SIGTERM` процессу с наибольшим `oom_score`
|
||||
- поддержка работы со `zram`, возможность реакции на `mem_used_total`
|
||||
@ -50,6 +50,7 @@ https://2ch.hk/s/res/2310304.html#2311483, https://archive.li/idixk
|
||||
- возможность задания `oom_score_min` для предотвращения убийства невиновных
|
||||
- verbosity: опциональность печати параметров конфига при старте программы, опциональность печати результатов проверки памяти и времени между проверками памяти
|
||||
- возможность предотвращения избыточного убийства процессов с помощью задания миниального `oom_score` для убиваемых процессов и установка минимальной задержки просле отправки сигналов (параметры конфига `min_delay_after_sigkill` и `min_delay_after_sigterm`)
|
||||
- возможность показа десктопных уведомлений
|
||||
- наличие `man` страницы
|
||||
- наличие установщика для пользователей `systemd`
|
||||
- протестировано на `Debian 9 x86_64`, `Debian 8 i386`, `Fedora 28 x86_64`
|
||||
|
93
nohang
93
nohang
@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Nohang - No Hang Daemon
|
||||
|
||||
# Nohang - The No Hang Daemon for Linux
|
||||
|
||||
################################################################################
|
||||
|
||||
@ -17,6 +16,10 @@ from argparse import ArgumentParser
|
||||
|
||||
### задание констант
|
||||
|
||||
version = 'unknown'
|
||||
|
||||
sig_dict = {9:'SIGKILL', 15:'SIGTERM'}
|
||||
|
||||
# директория, в которой запущен скрипт
|
||||
cd = os.getcwd()
|
||||
|
||||
@ -174,14 +177,39 @@ def find_victim_and_send_signal(signal):
|
||||
name = pid_to_name(pid)
|
||||
|
||||
print(
|
||||
' Try to send signal {} to {}, Pid {}, oom_score {}'.format(
|
||||
signal, name, pid, oom_score
|
||||
' Try to send the {} signal to {}, Pid {}, oom_score {}'.format(
|
||||
sig_dict[signal], name, pid, oom_score
|
||||
)
|
||||
)
|
||||
|
||||
try:
|
||||
os.kill(int(pid), signal)
|
||||
print(' Success')
|
||||
|
||||
if desktop_notifications:
|
||||
|
||||
info = '"The {} signal has been sent to <b>{}</b>,\n<i>Pid:</i> <b>{}</b>, <i>oom_score:</i> <b>{}</b>" &'.format(sig_dict[signal], name, pid, oom_score)
|
||||
|
||||
if root:
|
||||
# получаем множество залогиненных юзеров из вывода команды users
|
||||
users_set = set(str(
|
||||
Popen('users', shell=True, stdout=PIPE).communicate()[0][0:-1]
|
||||
)[2:-1].split(' '))
|
||||
# отправляем уведомление всем залогиненным юзерам
|
||||
for i in users_set:
|
||||
root_notify_command = 'DISPLAY=:0.0 sudo -u {} {} -i dialog-warnig "Nohang tried to prevent OOM" -t {} -u critical '.format(
|
||||
i, notify_command, notify_time
|
||||
)
|
||||
os.system(root_notify_command + info)
|
||||
else:
|
||||
user_notify_command =(
|
||||
'{} -i dialog-warnig "Nohang tried to prevent OOM" -t {} -u critical '.format(
|
||||
notify_command, notify_time
|
||||
)
|
||||
)
|
||||
os.system(user_notify_command + info)
|
||||
|
||||
|
||||
except ProcessLookupError:
|
||||
print(' No such process')
|
||||
except PermissionError:
|
||||
@ -326,6 +354,7 @@ else:
|
||||
exit()
|
||||
|
||||
|
||||
|
||||
if 'print_mem_check_results' in config_dict:
|
||||
print_mem_check_results = config_dict['print_mem_check_results']
|
||||
if print_mem_check_results == 'True':
|
||||
@ -345,6 +374,7 @@ else:
|
||||
exit()
|
||||
|
||||
|
||||
|
||||
if 'print_sleep_periods' in config_dict:
|
||||
print_sleep_periods = config_dict['print_sleep_periods']
|
||||
if print_sleep_periods == 'True':
|
||||
@ -400,11 +430,11 @@ else:
|
||||
|
||||
if 'self_oom_score_adj' in config_dict:
|
||||
self_oom_score_adj = config_dict['self_oom_score_adj']
|
||||
if string_to_int_convert_test(self_oom_score_adj) is None:
|
||||
self_oom_score_adj = string_to_int_convert_test(self_oom_score_adj)
|
||||
if self_oom_score_adj is None:
|
||||
print('Invalid self_oom_score_adj value, not integer\nExit')
|
||||
exit()
|
||||
else:
|
||||
self_oom_score_adj = int(self_oom_score_adj)
|
||||
if self_oom_score_adj < -1000 or self_oom_score_adj > 1000:
|
||||
print('Недопустимое значение self_oom_score_adj\nExit')
|
||||
exit()
|
||||
@ -593,6 +623,49 @@ else:
|
||||
exit()
|
||||
|
||||
|
||||
|
||||
if 'desktop_notifications' in config_dict:
|
||||
desktop_notifications = config_dict['desktop_notifications']
|
||||
if desktop_notifications == 'True':
|
||||
desktop_notifications = True
|
||||
from subprocess import Popen, PIPE
|
||||
elif desktop_notifications == 'False':
|
||||
desktop_notifications = False
|
||||
else:
|
||||
print(
|
||||
'Invalid desktop_notifications value {} (should be True or False)\nExit'.format(
|
||||
desktop_notifications
|
||||
)
|
||||
)
|
||||
exit()
|
||||
else:
|
||||
print('desktop_notifications not in config\nExit')
|
||||
exit()
|
||||
|
||||
|
||||
if 'notify_command' in config_dict:
|
||||
notify_command = config_dict['notify_command'].strip()
|
||||
else:
|
||||
print('notify_command not in config\nExit')
|
||||
exit()
|
||||
|
||||
|
||||
if 'notify_time' in config_dict:
|
||||
notify_time = config_dict['notify_time']
|
||||
notify_time = string_to_float_convert_test(notify_time)
|
||||
if notify_time is None:
|
||||
print('Invalid notify_time value, not float\nExit')
|
||||
exit()
|
||||
if notify_time <= 0:
|
||||
print('Недопустимое значение notify_time\nExit')
|
||||
exit()
|
||||
else:
|
||||
notify_time = int(notify_time * 1000)
|
||||
else:
|
||||
print('notify_time not in config\nExit')
|
||||
exit()
|
||||
|
||||
|
||||
################################################################################
|
||||
|
||||
### получение уровней в кибибайтах
|
||||
@ -732,7 +805,7 @@ if print_config:
|
||||
print('zram_max_sigterm: {}'.format(zram_max_sigterm))
|
||||
print('zram_max_sigkill: {}'.format(zram_max_sigkill))
|
||||
|
||||
print('\nV. ПРЕДОТВРАЩЕНИЕ УБИЙСТВ НЕВИНОВНЫХ')
|
||||
print('\nV. THE PREVENTION OF KILLING INNOCENT VICTIMS')
|
||||
print('min_delay_after_sigterm: {}'.format(min_delay_after_sigterm))
|
||||
print('min_delay_after_sigkill: {}'.format(min_delay_after_sigkill))
|
||||
print('oom_score_min: {}'.format(oom_score_min))
|
||||
@ -745,6 +818,11 @@ if print_config:
|
||||
print('oom_score_adj_before: {}'.format(oom_score_adj_before))
|
||||
print('oom_score_adj_after: {}'.format(oom_score_adj_after))
|
||||
|
||||
print('\nVI. DESKTOP NOTIFICATIONS')
|
||||
print('desktop_notifications: {}'.format(desktop_notifications))
|
||||
if desktop_notifications:
|
||||
print('notify_command: {}'.format(notify_command))
|
||||
print('notify_time: {}'.format(round(notify_time / 1000, 1)))
|
||||
|
||||
|
||||
# для рассчета ширины столбцов при печати mem и zram
|
||||
@ -757,7 +835,6 @@ print('\nStart monitoring...')
|
||||
|
||||
### цикл проверки уровней доступной памяти
|
||||
|
||||
|
||||
while True:
|
||||
|
||||
#decrease_oom_score_adj(oom_score_adj_before, oom_score_adj_after)
|
||||
|
25
nohang.conf
25
nohang.conf
@ -107,7 +107,7 @@ zram_max_sigkill = 60 %
|
||||
|
||||
#####################################################################
|
||||
|
||||
V. ПРЕДОТВРАЩЕНИЕ УБИЙСТВ НЕВИНОВНЫХ
|
||||
V. THE PREVENTION OF KILLING INNOCENT VICTIMS
|
||||
|
||||
Минимальное значение oom_score, которым должен обладать
|
||||
процесс для того, чтобы ему был отправлен сигнал.
|
||||
@ -122,7 +122,7 @@ oom_score_min = 15
|
||||
для предотвращения риска убийства сразу множества процессов.
|
||||
Должно быть неотрицательным числом.
|
||||
|
||||
min_delay_after_sigterm = 0.1
|
||||
min_delay_after_sigterm = 0.2
|
||||
min_delay_after_sigkill = 3
|
||||
|
||||
Процессы браузера chromium обычно имеют oom_score_adj
|
||||
@ -145,3 +145,24 @@ decrease_oom_score_adj = False
|
||||
oom_score_adj_before = 10
|
||||
oom_score_adj_after = 5
|
||||
|
||||
#####################################################################
|
||||
|
||||
VI. DESKTOP NOTIFICATIONS
|
||||
|
||||
Эта возможность требует наличия notify-send в системе.
|
||||
В Debian/Ubuntu это обеспечивается установкой пакета
|
||||
libnotify-bin. Также требуется наличие notification-daemon.
|
||||
Допустимые значения: True и False
|
||||
|
||||
desktop_notifications = False
|
||||
|
||||
Может использоваться другая команда, если ее синтаксис совместим
|
||||
с синтаксисом notify-send
|
||||
|
||||
notify_command = notify-send
|
||||
|
||||
Время показа уведомлений в секундах.
|
||||
Должно быть положительным числом.
|
||||
|
||||
notify_time = 15
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user