support EXECUTE THE COMMAND INSTEAD OF SENDING THE SIGTERM SIGNAL

This commit is contained in:
Alexey Avramov 2018-07-04 04:10:23 +09:00
parent 9bebbe38f9
commit c5a9478cd5
3 changed files with 89 additions and 18 deletions

View File

@ -74,6 +74,7 @@ https://www.reddit.com/r/linux/comments/5rixe9/this_is_why_i_love_linux_hundreds
- возможность показа десктопных уведомлений c помощью `notify-send`, с показом сигнала (`SIGTERM` или `SIGKILL`), который отправлен процессу, а также `Pid`, `oom_score`, `VmRSS`, `VmSwap`, которыми обладал процесс перед получением сигнала. - возможность показа десктопных уведомлений c помощью `notify-send`, с показом сигнала (`SIGTERM` или `SIGKILL`), который отправлен процессу, а также `Pid`, `oom_score`, `VmRSS`, `VmSwap`, которыми обладал процесс перед получением сигнала.
- поддержка white, black, prefer и avoid списков с использованием Perl-compatible regular expressions - поддержка white, black, prefer и avoid списков с использованием Perl-compatible regular expressions
- наличие `man` страницы - наличие `man` страницы
- возможность выполнения определенных команд как альтернатива отправке SIGTERM для избранных процессов (можно использовать для перезапуска демонов вместо завершения)
- поддержка журналирования в отдельный файл - поддержка журналирования в отдельный файл
- поддержка десктопных уведомлений о низком уровне доступной памяти - поддержка десктопных уведомлений о низком уровне доступной памяти
- наличие установщика для пользователей `systemd` - наличие установщика для пользователей `systemd`

73
nohang
View File

@ -411,26 +411,35 @@ def find_victim_and_send_signal(signal):
vm_rss = 0 vm_rss = 0
vm_swap = 0 vm_swap = 0
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) if name in etc_dict and signal is 15:
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)
print(etc_info)
os.system(etc_dict[name])
append_log(etc_info)
try: else:
os.kill(int(pid), signal) 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)
send_result = ' Success'
if desktop_notifications: print(try_to_send)
send_notify(signal, name, pid, oom_score, vm_rss, vm_swap)
except FileNotFoundError: try:
send_result = ' No such process' os.kill(int(pid), signal)
except ProcessLookupError: send_result = ' Success'
send_result = ' No such process'
print(send_result) if desktop_notifications:
send_notify(signal, name, pid, oom_score, vm_rss, vm_swap)
if logging: except FileNotFoundError:
append_log(try_to_send + '\n' + send_result) send_result = ' No such process'
except ProcessLookupError:
send_result = ' No such process'
print(send_result)
if logging:
append_log(try_to_send + '\n' + send_result)
else: else:
@ -547,17 +556,40 @@ print(config)
# парсинг конфига с получением словаря параметров # парсинг конфига с получением словаря параметров
# conf_parameters_dict
# conf_restart_dict
try: try:
with open(config) as f: with open(config) as f:
# словарь с параметрами конфига
config_dict = dict() config_dict = dict()
# словарь с именами и командами для параметра execute_the_command
etc_dict = dict()
for line in f: for line in f:
a = line.startswith('#') a = line.startswith('#')
b = line.startswith('\n') b = line.startswith('\n')
c = line.startswith('\t') c = line.startswith('\t')
d = line.startswith(' ') d = line.startswith(' ')
if not a and not b and not c and not d:
etc = line.startswith('**')
if not a and not b and not c and not d and not etc:
a = line.split('=') a = line.split('=')
config_dict[a[0].strip()] = a[1].strip() config_dict[a[0].strip()] = a[1].strip()
if etc:
a = line[2:].split('::')
etc_name = a[0].strip()
etc_command = a[1].strip()
if len(etc_name) > 15:
print('инвалид конфиг, длина имени процесса не должна превышать 15 символов\nExit')
exit()
etc_dict[etc_name] = etc_command
except PermissionError: except PermissionError:
print('PermissionError', conf_err_mess) print('PermissionError', conf_err_mess)
exit() exit()
@ -1087,6 +1119,9 @@ else:
exit() exit()
execute_the_command = conf_parse_bool('execute_the_command')
########################################################################## ##########################################################################
# получение уровней в кибибайтах # получение уровней в кибибайтах
@ -1266,6 +1301,14 @@ if print_config:
round(zram_max_warnings_mb), round(zram_max_warnings_percent, 1))) round(zram_max_warnings_mb), round(zram_max_warnings_percent, 1)))
print('\nX. EXECUTE THE COMMAND INSTEAD OF SENDING THE SIGTERM SIGNAL')
print('execute_the_command: {}'.format(execute_the_command))
if execute_the_command:
print('\nPROCESS NAME COMMAND TO EXECUTE')
for key in etc_dict:
print('{} {}'.format(key.ljust(15), etc_dict[key]))
########################################################################## ##########################################################################

View File

@ -20,7 +20,7 @@ print_config = True
Печатать ли результаты измерения доступной памяти. Печатать ли результаты измерения доступной памяти.
Допустимые значения: True и False Допустимые значения: True и False
print_mem_check_results = False print_mem_check_results = True
Печатать ли время сна между проверками памяти и после отправки Печатать ли время сна между проверками памяти и после отправки
сигналов. Можно установить в значение True для дебага. сигналов. Можно установить в значение True для дебага.
@ -94,8 +94,8 @@ rate_zram = 1
mem_min_sigterm = 8 % mem_min_sigterm = 8 %
mem_min_sigkill = 4 % mem_min_sigkill = 4 %
swap_min_sigterm = 8 % swap_min_sigterm = 50 %
swap_min_sigkill = 4 % swap_min_sigkill = 20 %
Задание общей доли zram в памяти, при превышении которой Задание общей доли zram в памяти, при превышении которой
происходит отправка соответствующих сигналов. происходит отправка соответствующих сигналов.
@ -278,3 +278,30 @@ swap_min_warnings = 20%
zram_max_warnings = 40 % zram_max_warnings = 40 %
#####################################################################
X. EXECUTE THE COMMAND INSTEAD OF SENDING THE SIGTERM SIGNAL
Для процессов с определенным именем можно задать команду,
которая будет выполняться вместо отправки сигнала SIGTERM
процессу с соответствующим именем.
Например, если процесс запущен как демон, то вместо
отправки SIGTERM можно выполнить команду перезапуска.
Допустимые значения: True и False.
execute_the_command = False
Длина имени процесса не должна превышать 15 символов.
Синтаксис таков: строки, начинающиеся с **, считаются строками,
содержащими имена процессов и соотвестствующие команды для
перезапуска этих процессов. После имени процесса через двойное
двоеточие (::) следует команда.
Например:
** mysqld :: systemctl restart mariadb.service &
** php-fpm7.0 :: systemctl restart php7.0-fpm.service &
Амперсанд (&) в конце команды позволит nohang продолжить работу
не дожидаясь окончания выполнения команды.
** processname :: some command &