обеспечена поддержка десктопных уведомлений
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` или новее
|
- требуется ядро `Linux 3.14` или новее
|
||||||
- периодически проверяет объем доступной памяти, при дефиците памяти отправляет `SIGKILL` или `SIGTERM` процессу с наибольшим `oom_score`
|
- периодически проверяет объем доступной памяти, при дефиците памяти отправляет `SIGKILL` или `SIGTERM` процессу с наибольшим `oom_score`
|
||||||
- поддержка работы со `zram`, возможность реакции на `mem_used_total`
|
- поддержка работы со `zram`, возможность реакции на `mem_used_total`
|
||||||
@ -50,6 +50,7 @@ https://2ch.hk/s/res/2310304.html#2311483, https://archive.li/idixk
|
|||||||
- возможность задания `oom_score_min` для предотвращения убийства невиновных
|
- возможность задания `oom_score_min` для предотвращения убийства невиновных
|
||||||
- verbosity: опциональность печати параметров конфига при старте программы, опциональность печати результатов проверки памяти и времени между проверками памяти
|
- verbosity: опциональность печати параметров конфига при старте программы, опциональность печати результатов проверки памяти и времени между проверками памяти
|
||||||
- возможность предотвращения избыточного убийства процессов с помощью задания миниального `oom_score` для убиваемых процессов и установка минимальной задержки просле отправки сигналов (параметры конфига `min_delay_after_sigkill` и `min_delay_after_sigterm`)
|
- возможность предотвращения избыточного убийства процессов с помощью задания миниального `oom_score` для убиваемых процессов и установка минимальной задержки просле отправки сигналов (параметры конфига `min_delay_after_sigkill` и `min_delay_after_sigterm`)
|
||||||
|
- возможность показа десктопных уведомлений
|
||||||
- наличие `man` страницы
|
- наличие `man` страницы
|
||||||
- наличие установщика для пользователей `systemd`
|
- наличие установщика для пользователей `systemd`
|
||||||
- протестировано на `Debian 9 x86_64`, `Debian 8 i386`, `Fedora 28 x86_64`
|
- протестировано на `Debian 9 x86_64`, `Debian 8 i386`, `Fedora 28 x86_64`
|
||||||
|
93
nohang
93
nohang
@ -1,7 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/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()
|
cd = os.getcwd()
|
||||||
|
|
||||||
@ -174,14 +177,39 @@ def find_victim_and_send_signal(signal):
|
|||||||
name = pid_to_name(pid)
|
name = pid_to_name(pid)
|
||||||
|
|
||||||
print(
|
print(
|
||||||
' Try to send signal {} to {}, Pid {}, oom_score {}'.format(
|
' Try to send the {} signal to {}, Pid {}, oom_score {}'.format(
|
||||||
signal, name, pid, oom_score
|
sig_dict[signal], name, pid, oom_score
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.kill(int(pid), signal)
|
os.kill(int(pid), signal)
|
||||||
print(' Success')
|
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:
|
except ProcessLookupError:
|
||||||
print(' No such process')
|
print(' No such process')
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
@ -326,6 +354,7 @@ else:
|
|||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if 'print_mem_check_results' in config_dict:
|
if 'print_mem_check_results' in config_dict:
|
||||||
print_mem_check_results = config_dict['print_mem_check_results']
|
print_mem_check_results = config_dict['print_mem_check_results']
|
||||||
if print_mem_check_results == 'True':
|
if print_mem_check_results == 'True':
|
||||||
@ -345,6 +374,7 @@ else:
|
|||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if 'print_sleep_periods' in config_dict:
|
if 'print_sleep_periods' in config_dict:
|
||||||
print_sleep_periods = config_dict['print_sleep_periods']
|
print_sleep_periods = config_dict['print_sleep_periods']
|
||||||
if print_sleep_periods == 'True':
|
if print_sleep_periods == 'True':
|
||||||
@ -400,11 +430,11 @@ else:
|
|||||||
|
|
||||||
if 'self_oom_score_adj' in config_dict:
|
if 'self_oom_score_adj' in config_dict:
|
||||||
self_oom_score_adj = config_dict['self_oom_score_adj']
|
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')
|
print('Invalid self_oom_score_adj value, not integer\nExit')
|
||||||
exit()
|
exit()
|
||||||
else:
|
else:
|
||||||
self_oom_score_adj = int(self_oom_score_adj)
|
|
||||||
if self_oom_score_adj < -1000 or self_oom_score_adj > 1000:
|
if self_oom_score_adj < -1000 or self_oom_score_adj > 1000:
|
||||||
print('Недопустимое значение self_oom_score_adj\nExit')
|
print('Недопустимое значение self_oom_score_adj\nExit')
|
||||||
exit()
|
exit()
|
||||||
@ -593,6 +623,49 @@ else:
|
|||||||
exit()
|
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_sigterm: {}'.format(zram_max_sigterm))
|
||||||
print('zram_max_sigkill: {}'.format(zram_max_sigkill))
|
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_sigterm: {}'.format(min_delay_after_sigterm))
|
||||||
print('min_delay_after_sigkill: {}'.format(min_delay_after_sigkill))
|
print('min_delay_after_sigkill: {}'.format(min_delay_after_sigkill))
|
||||||
print('oom_score_min: {}'.format(oom_score_min))
|
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_before: {}'.format(oom_score_adj_before))
|
||||||
print('oom_score_adj_after: {}'.format(oom_score_adj_after))
|
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
|
# для рассчета ширины столбцов при печати mem и zram
|
||||||
@ -757,7 +835,6 @@ print('\nStart monitoring...')
|
|||||||
|
|
||||||
### цикл проверки уровней доступной памяти
|
### цикл проверки уровней доступной памяти
|
||||||
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
|
||||||
#decrease_oom_score_adj(oom_score_adj_before, oom_score_adj_after)
|
#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, которым должен обладать
|
Минимальное значение 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
|
min_delay_after_sigkill = 3
|
||||||
|
|
||||||
Процессы браузера chromium обычно имеют oom_score_adj
|
Процессы браузера chromium обычно имеют oom_score_adj
|
||||||
@ -145,3 +145,24 @@ decrease_oom_score_adj = False
|
|||||||
oom_score_adj_before = 10
|
oom_score_adj_before = 10
|
||||||
oom_score_adj_after = 5
|
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