оптимизация уведомлений и потребления памяти
This commit is contained in:
parent
4847963277
commit
6231542d26
268
nohang
268
nohang
@ -7,7 +7,6 @@
|
|||||||
# импорты
|
# импорты
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from ctypes import CDLL
|
|
||||||
from operator import itemgetter
|
from operator import itemgetter
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
@ -16,10 +15,6 @@ from argparse import ArgumentParser
|
|||||||
|
|
||||||
# задание констант
|
# задание констант
|
||||||
|
|
||||||
#notify_options = '-t "60000"'
|
|
||||||
#notify_options = '-u "critical"'
|
|
||||||
notify_options = '-i "dialog-warning"'
|
|
||||||
|
|
||||||
version = 'unknown'
|
version = 'unknown'
|
||||||
|
|
||||||
sig_dict = {9: 'SIGKILL', 15: 'SIGTERM'}
|
sig_dict = {9: 'SIGKILL', 15: 'SIGTERM'}
|
||||||
@ -34,7 +29,8 @@ default_configs = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
# универсальное сообщение при инвалидном конфиге
|
# универсальное сообщение при инвалидном конфиге
|
||||||
conf_err_mess = '\nSet up the path to the valid config file with -c/--config CONFIG option!\nExit'
|
conf_err_mess = '\nSet up the path to the valid config file with -c/--confi' \
|
||||||
|
'g option!\nExit'
|
||||||
|
|
||||||
# означает, что при задани zram disksize = 10000M доступная память
|
# означает, что при задани zram disksize = 10000M доступная память
|
||||||
# уменьшится на 42M
|
# уменьшится на 42M
|
||||||
@ -77,7 +73,7 @@ def func_decrease_oom_score_adj(oom_score_adj_max):
|
|||||||
oom_score_adj = int(rline1('/proc/' + i + '/oom_score_adj'))
|
oom_score_adj = int(rline1('/proc/' + i + '/oom_score_adj'))
|
||||||
if oom_score_adj > oom_score_adj_max:
|
if oom_score_adj > oom_score_adj_max:
|
||||||
write('/proc/' + i + '/oom_score_adj',
|
write('/proc/' + i + '/oom_score_adj',
|
||||||
str(oom_score_adj_max) + '\n')
|
str(oom_score_adj_max) + '\n')
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
pass
|
pass
|
||||||
except ProcessLookupError:
|
except ProcessLookupError:
|
||||||
@ -150,11 +146,36 @@ def pid_to_name(pid):
|
|||||||
return '<unknown>'
|
return '<unknown>'
|
||||||
|
|
||||||
|
|
||||||
|
def send_notify(signal, name, pid, oom_score, vm_rss, vm_swap):
|
||||||
|
|
||||||
|
# текст отправляемого уведомления
|
||||||
|
info = '"<u>Nohang</u> sent <u>{}</u> \nto the process <b>{}</b> \n<i>P' \
|
||||||
|
'id:</i> <b>{}</b> \n<i>oom_score:</i> <b>{}</b> \n<i>VmRSS:</i> <b' \
|
||||||
|
'>{} MiB</b> \n<i>VmSwap:</i> <b>{} MiB</b>" &'.format(
|
||||||
|
sig_dict[signal], name, pid, oom_score, vm_rss, vm_swap)
|
||||||
|
|
||||||
|
if root:
|
||||||
|
for uid in os.listdir('/run/user'):
|
||||||
|
root_notify_command = 'DISPLAY=:0 sudo -u {} notify-send {} "Pr' \
|
||||||
|
'eventing OOM" '.format(users_dict[uid], 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)
|
||||||
|
|
||||||
|
|
||||||
|
# принимает int (9 или 15)
|
||||||
def find_victim_and_send_signal(signal):
|
def find_victim_and_send_signal(signal):
|
||||||
|
|
||||||
|
# выставляем потолок для 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)
|
||||||
|
|
||||||
|
# получаем список процессов
|
||||||
oom_list = []
|
oom_list = []
|
||||||
for i in os.listdir('/proc'):
|
for i in os.listdir('/proc'):
|
||||||
if i.isdigit() is not True:
|
if i.isdigit() is not True:
|
||||||
@ -167,8 +188,10 @@ 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))
|
||||||
|
|
||||||
# получаем список пар (pid, oom_score)
|
# получаем отсортированный по oom_score список пар (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 = pid_tuple_list[1]
|
oom_score = pid_tuple_list[1]
|
||||||
|
|
||||||
# посылаем сигнал
|
# посылаем сигнал
|
||||||
@ -178,43 +201,38 @@ def find_victim_and_send_signal(signal):
|
|||||||
|
|
||||||
name = pid_to_name(pid)
|
name = pid_to_name(pid)
|
||||||
|
|
||||||
with open('/proc/' + pid + '/status') as f:
|
# находим VmRSS и VmSwap процесса, которому попытаемся послать сигнал
|
||||||
for n, line in enumerate(f):
|
try:
|
||||||
|
with open('/proc/' + pid + '/status') as f:
|
||||||
|
for n, line in enumerate(f):
|
||||||
|
if n is vm_rss_index:
|
||||||
|
vm_rss = kib_to_mib(int(
|
||||||
|
line.split('\t')[1][:-4]))
|
||||||
|
continue
|
||||||
|
if n is vm_swap_index:
|
||||||
|
vm_swap = kib_to_mib(int(
|
||||||
|
line.split('\t')[1][:-4]))
|
||||||
|
break
|
||||||
|
except FileNotFoundError:
|
||||||
|
vm_rss = 0
|
||||||
|
vm_swap = 0
|
||||||
|
except ProcessLookupError:
|
||||||
|
vm_rss = 0
|
||||||
|
vm_swap = 0
|
||||||
|
except IndexError:
|
||||||
|
vm_rss = 0
|
||||||
|
vm_swap = 0
|
||||||
|
|
||||||
if n is vm_rss_index:
|
print(' Try to send the {} signal to {},\n Pid {}, oom_score {}, V'
|
||||||
vm_rss = kib_to_mib(int(line.split(':')[1].split(' ')[-2]))
|
'mRSS {} MiB, VmSwap {} MiB'.format(
|
||||||
continue
|
sig_dict[signal], name, pid, oom_score, vm_rss, vm_swap))
|
||||||
|
|
||||||
if n is vm_swap_index:
|
|
||||||
vm_swap = kib_to_mib(int(line.split(':')[1].split(' ')[-2]))
|
|
||||||
break
|
|
||||||
|
|
||||||
print(' Try to send the {} signal to {},\n Pid {}, oom_score {}, VmRSS {} MiB, VmSwap {} MiB'.format(
|
|
||||||
sig_dict[signal], name, pid, oom_score, vm_rss, vm_swap))
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
os.kill(int(pid), signal)
|
os.kill(int(pid), signal)
|
||||||
print(' Success')
|
print(' Success')
|
||||||
|
|
||||||
if desktop_notifications:
|
if desktop_notifications:
|
||||||
|
send_notify(signal, name, pid, oom_score, vm_rss, vm_swap)
|
||||||
info = '"<u>Nohang</u> sent <u>{}</u> \nto the process \n<i>Name:</i> <b>{}</b> \n<i>Pid:</i> <b>{}</b> \n<i>oom_score:</i> <b>{}</b> \n<i>VmRSS:</i> <b>{} MiB</b> \n<i>VmSwap:</i> <b>{} MiB</b>" &'.format(sig_dict[signal], name, pid, oom_score, vm_rss, vm_swap)
|
|
||||||
|
|
||||||
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 sudo -u {} notify-send {} "Preventing OOM" '.format(
|
|
||||||
i, notify_options)
|
|
||||||
os.system(root_notify_command + info)
|
|
||||||
else:
|
|
||||||
user_notify_command = 'notify-send {} "Preventing OOM" '.format(notify_options)
|
|
||||||
os.system(user_notify_command + info)
|
|
||||||
|
|
||||||
except ProcessLookupError:
|
except ProcessLookupError:
|
||||||
print(' No such process')
|
print(' No such process')
|
||||||
@ -236,11 +254,11 @@ def find_victim_and_send_signal(signal):
|
|||||||
print(' sleep', min_delay_after_sigterm)
|
print(' sleep', min_delay_after_sigterm)
|
||||||
sleep(min_delay_after_sigterm)
|
sleep(min_delay_after_sigterm)
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
# поиск позиций и mem_total
|
# поиск позиций и mem_total
|
||||||
|
|
||||||
|
|
||||||
with open('/proc/meminfo') as file:
|
with open('/proc/meminfo') as file:
|
||||||
mem_list = file.readlines()
|
mem_list = file.readlines()
|
||||||
|
|
||||||
@ -283,7 +301,9 @@ parser.add_argument(
|
|||||||
type=str
|
type=str
|
||||||
)
|
)
|
||||||
|
|
||||||
arg_config = parser.parse_args().config
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
arg_config = args.config
|
||||||
|
|
||||||
|
|
||||||
if arg_config is None:
|
if arg_config is None:
|
||||||
@ -337,7 +357,6 @@ except IndexError:
|
|||||||
print('IndexError', conf_err_mess)
|
print('IndexError', conf_err_mess)
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
# извлечение параметров из словаря
|
# извлечение параметров из словаря
|
||||||
@ -352,11 +371,9 @@ if 'print_config' in config_dict:
|
|||||||
elif print_config == 'False':
|
elif print_config == 'False':
|
||||||
print_config = False
|
print_config = False
|
||||||
else:
|
else:
|
||||||
print(
|
print('Invalid print_config value {} (should be True or False)\nE'
|
||||||
'Invalid print_config value {} (should be True or False)\nExit'.format(
|
'xit'.format(
|
||||||
print_config
|
print_config))
|
||||||
)
|
|
||||||
)
|
|
||||||
exit()
|
exit()
|
||||||
else:
|
else:
|
||||||
print('Print_config not in config\nExit')
|
print('Print_config not in config\nExit')
|
||||||
@ -370,8 +387,9 @@ if 'print_mem_check_results' in config_dict:
|
|||||||
elif print_mem_check_results == 'False':
|
elif print_mem_check_results == 'False':
|
||||||
print_mem_check_results = False
|
print_mem_check_results = False
|
||||||
else:
|
else:
|
||||||
print('Invalid print_mem_check_results value {} (should be True or False)\nExit'.format(
|
print('Invalid print_mem_check_results value {} (should be Tr'
|
||||||
print_mem_check_results))
|
'ue or False)\nExit'.format(
|
||||||
|
print_mem_check_results))
|
||||||
exit()
|
exit()
|
||||||
else:
|
else:
|
||||||
print('print_mem_check_results not in config\nExit')
|
print('print_mem_check_results not in config\nExit')
|
||||||
@ -385,8 +403,9 @@ if 'print_sleep_periods' in config_dict:
|
|||||||
elif print_sleep_periods == 'False':
|
elif print_sleep_periods == 'False':
|
||||||
print_sleep_periods = False
|
print_sleep_periods = False
|
||||||
else:
|
else:
|
||||||
print('Invalid print_sleep_periods value {} (should be True or False)\nExit'.format(
|
print('Invalid print_sleep_periods value {} (should be True or F'
|
||||||
print_sleep_periods))
|
'alse)\nExit'.format(
|
||||||
|
print_sleep_periods))
|
||||||
exit()
|
exit()
|
||||||
else:
|
else:
|
||||||
print('print_sleep_periods not in config\nExit')
|
print('print_sleep_periods not in config\nExit')
|
||||||
@ -577,8 +596,9 @@ if 'decrease_oom_score_adj' in config_dict:
|
|||||||
elif decrease_oom_score_adj == 'False':
|
elif decrease_oom_score_adj == 'False':
|
||||||
decrease_oom_score_adj = False
|
decrease_oom_score_adj = False
|
||||||
else:
|
else:
|
||||||
print('invalid decrease_oom_score_adj value {} (should be True or False)\nExit'.format(
|
print('invalid decrease_oom_score_adj value {} (should be Tru'
|
||||||
decrease_oom_score_adj))
|
'e or False)\nExit'.format(
|
||||||
|
decrease_oom_score_adj))
|
||||||
exit()
|
exit()
|
||||||
else:
|
else:
|
||||||
print('decrease_oom_score_adj not in config\nExit')
|
print('decrease_oom_score_adj not in config\nExit')
|
||||||
@ -604,18 +624,31 @@ if 'desktop_notifications' in config_dict:
|
|||||||
desktop_notifications = config_dict['desktop_notifications']
|
desktop_notifications = config_dict['desktop_notifications']
|
||||||
if desktop_notifications == 'True':
|
if desktop_notifications == 'True':
|
||||||
desktop_notifications = True
|
desktop_notifications = True
|
||||||
from subprocess import Popen, PIPE
|
users_dict = dict()
|
||||||
|
with open('/etc/passwd') as f:
|
||||||
|
for line in f:
|
||||||
|
line_list = line.split(':')
|
||||||
|
username = line_list[0]
|
||||||
|
uid = line_list[2]
|
||||||
|
users_dict[uid] = username
|
||||||
elif desktop_notifications == 'False':
|
elif desktop_notifications == 'False':
|
||||||
desktop_notifications = False
|
desktop_notifications = False
|
||||||
else:
|
else:
|
||||||
print('Invalid desktop_notifications value {} (should be True or False)\nExit'.format(
|
print('Invalid desktop_notifications value {} (should be Tru'
|
||||||
desktop_notifications))
|
'e or False)\nExit'.format(
|
||||||
|
desktop_notifications))
|
||||||
exit()
|
exit()
|
||||||
else:
|
else:
|
||||||
print('desktop_notifications not in config\nExit')
|
print('desktop_notifications not in config\nExit')
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
|
||||||
|
if 'notify_options' in config_dict:
|
||||||
|
notify_options = config_dict['notify_options'].strip()
|
||||||
|
else:
|
||||||
|
print('notify_options not in config\nExit')
|
||||||
|
exit()
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
# получение уровней в кибибайтах
|
# получение уровней в кибибайтах
|
||||||
@ -677,7 +710,6 @@ else:
|
|||||||
swap_kill_is_percent = False
|
swap_kill_is_percent = False
|
||||||
swap_min_sigkill_kb = swap_min_sigkill_swap
|
swap_min_sigkill_kb = swap_min_sigkill_swap
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
# самозащита и печать конфига
|
# самозащита и печать конфига
|
||||||
@ -705,6 +737,7 @@ except OSError:
|
|||||||
|
|
||||||
# запрет своппинга процесса
|
# запрет своппинга процесса
|
||||||
if mlockall:
|
if mlockall:
|
||||||
|
from ctypes import CDLL
|
||||||
result = CDLL('libc.so.6', use_errno=True).mlockall(3)
|
result = CDLL('libc.so.6', use_errno=True).mlockall(3)
|
||||||
if result is 0:
|
if result is 0:
|
||||||
mla_res = 'OK'
|
mla_res = 'OK'
|
||||||
@ -765,6 +798,8 @@ if print_config:
|
|||||||
|
|
||||||
print('\nVI. DESKTOP NOTIFICATIONS')
|
print('\nVI. DESKTOP NOTIFICATIONS')
|
||||||
print('desktop_notifications: {}'.format(desktop_notifications))
|
print('desktop_notifications: {}'.format(desktop_notifications))
|
||||||
|
if desktop_notifications:
|
||||||
|
print('notify_options: {}'.format(notify_options))
|
||||||
|
|
||||||
|
|
||||||
# для рассчета ширины столбцов при печати mem и zram
|
# для рассчета ширины столбцов при печати mem и zram
|
||||||
@ -784,13 +819,13 @@ while True:
|
|||||||
with open('/proc/meminfo') as f:
|
with open('/proc/meminfo') as f:
|
||||||
for n, line in enumerate(f):
|
for n, line in enumerate(f):
|
||||||
if n is 2:
|
if n is 2:
|
||||||
mem_available = int(line.split(':')[1].split(' ')[-2])
|
mem_available = int(line.split(':')[1].strip(' kB\n'))
|
||||||
continue
|
continue
|
||||||
if n is swap_total_index:
|
if n is swap_total_index:
|
||||||
swap_total = int(line.split(':')[1].split(' ')[-2])
|
swap_total = int(line.split(':')[1].strip(' kB\n'))
|
||||||
continue
|
continue
|
||||||
if n is swap_free_index:
|
if n is swap_free_index:
|
||||||
swap_free = int(line.split(':')[1].split(' ')[-2])
|
swap_free = int(line.split(':')[1].strip(' kB\n'))
|
||||||
break
|
break
|
||||||
|
|
||||||
# если swap_min_sigkill задан в процентах
|
# если swap_min_sigkill задан в процентах
|
||||||
@ -818,35 +853,28 @@ while True:
|
|||||||
# печать размеров доступной памяти
|
# печать размеров доступной памяти
|
||||||
if swap_total == 0 and mem_used_zram == 0:
|
if swap_total == 0 and mem_used_zram == 0:
|
||||||
if print_mem_check_results:
|
if print_mem_check_results:
|
||||||
print(
|
print('MemAvail: {} M, {} %'.format(
|
||||||
'MemAvail: {} M, {} %'.format(
|
human(mem_available, mem_len),
|
||||||
human(mem_available, mem_len),
|
just_percent_mem(mem_available / mem_total)))
|
||||||
just_percent_mem(mem_available / mem_total)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
elif swap_total > 0 and mem_used_zram == 0:
|
elif swap_total > 0 and mem_used_zram == 0:
|
||||||
if print_mem_check_results:
|
if print_mem_check_results:
|
||||||
print(
|
print('MemAvail: {} M, {} % | SwapFree: {} M, {} %'.format(
|
||||||
'MemAvail: {} M, {} % | SwapFree: {} M, {} %'.format(
|
human(mem_available, mem_len),
|
||||||
human(mem_available, mem_len),
|
just_percent_mem(mem_available / mem_total),
|
||||||
just_percent_mem(mem_available / mem_total),
|
human(swap_free, swap_len),
|
||||||
human(swap_free, swap_len),
|
just_percent_swap(swap_free / (swap_total + 0.0001))))
|
||||||
just_percent_swap(swap_free / (swap_total + 0.0001))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
if print_mem_check_results:
|
if print_mem_check_results:
|
||||||
print(
|
print('MemAvail: {} M, {} % | SwapFree: {} M, {} % | MemUsed'
|
||||||
'MemAvail: {} M, {} % | SwapFree: {} M, {} % | MemUsed'
|
'Zram: {} M, {} %'.format(
|
||||||
'Zram: {} M, {} %'.format(
|
human(mem_available, mem_len),
|
||||||
human(mem_available, mem_len),
|
just_percent_mem(mem_available / mem_total),
|
||||||
just_percent_mem(mem_available / mem_total),
|
human(swap_free, swap_len),
|
||||||
human(swap_free, swap_len),
|
just_percent_swap(swap_free / (swap_total + 0.0001)),
|
||||||
just_percent_swap(swap_free / (swap_total + 0.0001)),
|
human(mem_used_zram, mem_len),
|
||||||
human(mem_used_zram, mem_len),
|
just_percent_mem(mem_used_zram / mem_total)))
|
||||||
just_percent_mem(mem_used_zram / mem_total)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
# если swap_min_sigkill задан в абсолютной величине и Swap_total = 0
|
# если swap_min_sigkill задан в абсолютной величине и Swap_total = 0
|
||||||
if swap_total > swap_min_sigkill_kb:
|
if swap_total > swap_min_sigkill_kb:
|
||||||
@ -861,61 +889,51 @@ while True:
|
|||||||
|
|
||||||
# MEM SWAP KILL
|
# MEM SWAP KILL
|
||||||
if mem_available <= mem_min_sigkill_kb and swap_free <= swap_min_sigkill_kb:
|
if mem_available <= mem_min_sigkill_kb and swap_free <= swap_min_sigkill_kb:
|
||||||
print(
|
print('+ MemAvail ({} M, {} %) < mem_min_sigkill ({} M, {} %)\n S'
|
||||||
'+ MemAvail ({} M, {} %) < mem_min_sigkill ({} M, {} %)\n S'
|
'wapFree ({} M, {} %) < swap_min_sigkill ({} M, {} %)'.format(
|
||||||
'wapFree ({} M, {} %) < swap_min_sigkill ({} M, {} %)'.format(
|
kib_to_mib(mem_available),
|
||||||
kib_to_mib(mem_available),
|
percent(mem_available / mem_total),
|
||||||
percent(mem_available / mem_total),
|
kib_to_mib(mem_min_sigkill_kb),
|
||||||
kib_to_mib(mem_min_sigkill_kb),
|
percent(mem_min_sigkill_kb / mem_total),
|
||||||
percent(mem_min_sigkill_kb / mem_total),
|
kib_to_mib(swap_free),
|
||||||
kib_to_mib(swap_free),
|
percent(swap_free / (swap_total + 0.0001)),
|
||||||
percent(swap_free / (swap_total + 0.0001)),
|
kib_to_mib(swap_min_sigkill_kb),
|
||||||
kib_to_mib(swap_min_sigkill_kb),
|
swap_sigkill_pc))
|
||||||
swap_sigkill_pc
|
|
||||||
)
|
|
||||||
)
|
|
||||||
find_victim_and_send_signal(9)
|
find_victim_and_send_signal(9)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# ZRAM KILL
|
# ZRAM KILL
|
||||||
if mem_used_zram >= zram_max_sigkill_kb:
|
if mem_used_zram >= zram_max_sigkill_kb:
|
||||||
print(
|
print('+ MemUsedZram ({} M, {} %) > zram_max_sigkill ({} M, {} %)'.format(
|
||||||
'+ MemUsedZram ({} M, {} %) > zram_max_sigkill ({} M, {} %)'.format(
|
kib_to_mib(mem_used_zram),
|
||||||
kib_to_mib(mem_used_zram),
|
percent(mem_used_zram / mem_total),
|
||||||
percent(
|
kib_to_mib(zram_max_sigkill_kb),
|
||||||
mem_used_zram /
|
percent(zram_max_sigkill_kb / mem_total)))
|
||||||
mem_total),
|
|
||||||
kib_to_mib(zram_max_sigkill_kb),
|
|
||||||
percent(
|
|
||||||
zram_max_sigkill_kb /
|
|
||||||
mem_total)))
|
|
||||||
find_victim_and_send_signal(9)
|
find_victim_and_send_signal(9)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# MEM SWAP TERM
|
# MEM SWAP TERM
|
||||||
if mem_available <= mem_min_sigterm_kb and swap_free <= swap_min_sigterm_kb:
|
if mem_available <= mem_min_sigterm_kb and swap_free <= swap_min_sigterm_kb:
|
||||||
print('+ MemAvail ({} M, {} %) < mem_min_sigterm ({} M, {} %)\n SwapFree ({} M, {} %) < swap_min_sigterm ({} M, {} %)'.format(
|
print('+ MemAvail ({} M, {} %) < mem_min_sigterm ({} M, {} %)\n S'
|
||||||
kib_to_mib(mem_available),
|
'wapFree ({} M, {} %) < swap_min_sigterm ({} M, {} %)'.format(
|
||||||
percent(mem_available / mem_total),
|
kib_to_mib(mem_available),
|
||||||
kib_to_mib(mem_min_sigterm_kb),
|
percent(mem_available / mem_total),
|
||||||
percent(mem_min_sigterm_kb / mem_total),
|
kib_to_mib(mem_min_sigterm_kb),
|
||||||
kib_to_mib(swap_free),
|
percent(mem_min_sigterm_kb / mem_total),
|
||||||
percent(swap_free / (swap_total + 0.0001)),
|
kib_to_mib(swap_free),
|
||||||
kib_to_mib(swap_min_sigterm_kb),
|
percent(swap_free / (swap_total + 0.0001)),
|
||||||
swap_sigterm_pc))
|
kib_to_mib(swap_min_sigterm_kb),
|
||||||
|
swap_sigterm_pc))
|
||||||
find_victim_and_send_signal(15)
|
find_victim_and_send_signal(15)
|
||||||
|
|
||||||
# ZRAM TERM
|
# ZRAM TERM
|
||||||
if mem_used_zram >= zram_max_sigterm_kb:
|
if mem_used_zram >= zram_max_sigterm_kb:
|
||||||
print('+ MemUsedZram ({} M, {} %) > zram_max_sigterm ({} M, {} %)'.format(
|
print('+ MemUsedZram ({} M, {} %) > zram_max_sigt'
|
||||||
kib_to_mib(mem_used_zram),
|
'erm ({} M, {} %)'.format(
|
||||||
percent(
|
kib_to_mib(mem_used_zram),
|
||||||
mem_used_zram /
|
percent(mem_used_zram / mem_total),
|
||||||
mem_total),
|
kib_to_mib(zram_max_sigterm_kb),
|
||||||
kib_to_mib(zram_max_sigterm_kb),
|
percent(zram_max_sigterm_kb / mem_total)))
|
||||||
percent(
|
|
||||||
zram_max_sigterm_kb /
|
|
||||||
mem_total)))
|
|
||||||
find_victim_and_send_signal(15)
|
find_victim_and_send_signal(15)
|
||||||
|
|
||||||
# задание периода в зависимости от рейтов и уровней доступной памяти
|
# задание периода в зависимости от рейтов и уровней доступной памяти
|
||||||
|
26
nohang.conf
26
nohang.conf
@ -12,19 +12,19 @@
|
|||||||
Печатать параметров конфига при запуске программы.
|
Печатать параметров конфига при запуске программы.
|
||||||
Допустимые значения: True и False
|
Допустимые значения: True и False
|
||||||
|
|
||||||
print_config = True
|
print_config = False
|
||||||
|
|
||||||
Печатать ли результаты измерения доступной памяти.
|
Печатать ли результаты измерения доступной памяти.
|
||||||
Допустимые значения: True и False
|
Допустимые значения: True и False
|
||||||
|
|
||||||
print_mem_check_results = True
|
print_mem_check_results = False
|
||||||
|
|
||||||
Печатать ли время сна между проверками памяти и после отправки
|
Печатать ли время сна между проверками памяти и после отправки
|
||||||
сигналов. Можно установить в значение True для дебага.
|
сигналов. Можно установить в значение True для дебага.
|
||||||
Допустимые значения: True и False
|
Допустимые значения: True и False
|
||||||
(В этой ветке по дефолту True)
|
(В этой ветке по дефолту True)
|
||||||
|
|
||||||
print_sleep_periods = True
|
print_sleep_periods = False
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ print_sleep_periods = True
|
|||||||
В Fedora 28 значение True вызывает увеличение потребления
|
В Fedora 28 значение True вызывает увеличение потребления
|
||||||
памяти процессом на 200 MiB, в Debian 8 и 9 такой проблемы нет.
|
памяти процессом на 200 MiB, в Debian 8 и 9 такой проблемы нет.
|
||||||
|
|
||||||
mlockall = False
|
mlockall = True
|
||||||
|
|
||||||
Установка отрицательных значений self_nice и self_oom_score_adj
|
Установка отрицательных значений self_nice и self_oom_score_adj
|
||||||
требует наличия root прав.
|
требует наличия root прав.
|
||||||
@ -71,9 +71,9 @@ self_oom_score_adj = -1000
|
|||||||
достаточно хорошо, успешно справляясь с резкими скачками потребления
|
достаточно хорошо, успешно справляясь с резкими скачками потребления
|
||||||
памяти.
|
памяти.
|
||||||
|
|
||||||
rate_mem = 3
|
rate_mem = 6
|
||||||
rate_swap = 1
|
rate_swap = 3
|
||||||
rate_zram = 0.5
|
rate_zram = 1
|
||||||
|
|
||||||
#####################################################################
|
#####################################################################
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ min_delay_after_sigkill = 3
|
|||||||
|
|
||||||
Требует root прав.
|
Требует root прав.
|
||||||
|
|
||||||
decrease_oom_score_adj = True
|
decrease_oom_score_adj = False
|
||||||
|
|
||||||
Допустимые значения - целые числа из диапазона [0; 1000]
|
Допустимые значения - целые числа из диапазона [0; 1000]
|
||||||
|
|
||||||
@ -147,15 +147,21 @@ oom_score_adj_max = 50
|
|||||||
VI. DESKTOP NOTIFICATIONS
|
VI. DESKTOP NOTIFICATIONS
|
||||||
|
|
||||||
Эта возможность требует наличия notify-send в системе.
|
Эта возможность требует наличия notify-send в системе.
|
||||||
|
|
||||||
В Debian/Ubuntu это обеспечивается установкой пакета
|
В Debian/Ubuntu это обеспечивается установкой пакета
|
||||||
libnotify-bin. В Fedora и Arch Linux - пакет libnotify.
|
libnotify-bin. В Fedora и Arch Linux - пакет libnotify.
|
||||||
Также требуется наличие notification-daemon.
|
Также требуется наличие notification-daemon.
|
||||||
При запуске nohang от рута уведомления рассылаются всем
|
При запуске nohang от рута уведомления рассылаются всем
|
||||||
залогиненным пользователям.
|
залогиненным пользователям.
|
||||||
See also wiki.archlinux.org/index.php/Desktop_notifications
|
See also wiki.archlinux.org/index.php/Desktop_notifications
|
||||||
|
|
||||||
Допустимые значения: True и False
|
Допустимые значения: True и False
|
||||||
|
|
||||||
desktop_notifications = True
|
desktop_notifications = True
|
||||||
|
|
||||||
|
Дополнительные опции для notify-send.
|
||||||
|
См. notify-send --help и man notify-send
|
||||||
|
Примеры:
|
||||||
|
notify_options = -u "critical"
|
||||||
|
notify_options = -t "20000" -i "dialog-warning"
|
||||||
|
|
||||||
|
notify_options = -u "normal"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user