diff --git a/nohang b/nohang
index 0eba8f6..c079dcf 100755
--- a/nohang
+++ b/nohang
@@ -1,7 +1,5 @@
-#!/usr/bin/env python3
-
-# A daemon that prevents out of memory
-
+#!/usr/bin/python
+"""A daemon that prevents OOM in linux systems."""
import os
import signal
from operator import itemgetter
@@ -11,7 +9,7 @@ from sys import stdout
sig_dict = {signal.SIGKILL: 'SIGKILL',
- signal.SIGTERM: 'SIGTERM'}
+ signal.SIGTERM: 'SIGTERM'}
# directory where the script is running
cd = os.getcwd()
@@ -42,17 +40,19 @@ zram_disksize_factor = 0.0042
# function definition section
-# return list of tuples with
-# username, DISPLAY and DBUS_SESSION_BUS_ADDRESS
def root_notify_env():
+ """
+ Get environment for notification sending from root.
+ Returns list [tuple username, tuple DISPLAY, tuple DBUS_SESSION_BUS_ADDRES]
+ """
ps_output_list = Popen(['ps', 'ae'], stdout=PIPE
- ).communicate()[0].decode().split('\n')
+ ).communicate()[0].decode().split('\n')
lines_with_displays = []
for line in ps_output_list:
if ' DISPLAY=' in line and ' DBUS_SESSION_BUS_ADDRES' \
- 'S=' in line and ' USER=' in line:
+ 'S=' in line and ' USER=' in line:
lines_with_displays.append(line)
# list of tuples with needments
@@ -79,6 +79,7 @@ def root_notify_env():
def string_to_float_convert_test(string):
+ """Try to interprete string values as floats."""
try:
return float(string)
except ValueError:
@@ -86,6 +87,7 @@ def string_to_float_convert_test(string):
def string_to_int_convert_test(string):
+ """Try to interpretst string values as integers."""
try:
return int(string)
except ValueError:
@@ -94,6 +96,12 @@ def string_to_int_convert_test(string):
# extracting the parameter from the config dictionary, str return
def conf_parse_string(param):
+ """
+ Get string parameters from the config dict.
+
+ param: config_dict key
+ returns config_dict[param].strip()
+ """
if param in config_dict:
return config_dict[param].strip()
else:
@@ -104,6 +112,12 @@ def conf_parse_string(param):
# extracting the parameter from the config dictionary, bool return
def conf_parse_bool(param):
+ """
+ Get bool parameters from the config_dict.
+
+ param: config_dicst key
+ returns bool
+ """
if param in config_dict:
param_str = config_dict[param]
if param_str == 'True':
@@ -122,6 +136,9 @@ def conf_parse_bool(param):
def func_decrease_oom_score_adj(oom_score_adj_max):
+ """
+ Pls, put description here...
+ """
for i in os.listdir('/proc'):
if i.isdigit() is not True:
continue
@@ -136,28 +153,31 @@ def func_decrease_oom_score_adj(oom_score_adj_max):
pass
-# read 1st line
def rline1(path):
+ """read 1st line from path."""
with open(path) as f:
for line in f:
return line[:-1]
-# write in file
def write(path, string):
+ """Write string to path."""
with open(path, 'w') as f:
f.write(string)
def kib_to_mib(num):
+ """Convert Kib values to Mib values."""
return round(num / 1024.0)
def percent(num):
+ """Interprete mum as percentage."""
return round(num * 100, 1)
def just_percent_mem(num):
+ """Pls, put description here..."""
return str(round(num * 100, 1)).rjust(4, ' ')
@@ -167,11 +187,18 @@ def just_percent_swap(num):
# KiB to MiB, right alignment
def human(num, lenth):
+ """Convert Kib values to Mib values with right alignment"""
return str(round(num / 1024)).rjust(lenth, ' ')
# return str with amount of bytes
def zram_stat(zram_id):
+ """
+ Get zram state.
+
+ zram_id: str zram block-device id
+ returns bytes diskcize, str mem_used_total
+ """
try:
disksize = rline1('/sys/block/' + zram_id + '/disksize')
except FileNotFoundError:
@@ -192,6 +219,12 @@ def zram_stat(zram_id):
# return process name
def pid_to_name(pid):
+ """
+ Get process name by pid.
+
+ pid: str pid of required process
+ returns string process_name
+ """
try:
with open('/proc/' + pid + '/status') as f:
for line in f:
@@ -203,7 +236,11 @@ def pid_to_name(pid):
def send_notify_warn():
+ """
+ Look for process with maximum 'badness' and warn user with notification.
+
+ """
# find process with max badness
fat_tuple = fattest()
pid = fat_tuple[1]
@@ -225,20 +262,29 @@ def send_notify_warn():
title = 'Low memory: {}'.format(low_mem_percent)
body = 'Fattest process: {}, {}'.format(pid, name)
- if root:
- # send notification to all active users
- Popen(['/usr/sbin/nohang_notify_low_mem', '--mem', low_mem_percent, '--pid', pid, '--name', name])
- else:
- # отправляем уведомление пользователю, который запустил nohang
- Popen(['notify-send', '--icon=dialog-warning', 'Low memory: {}'.format(title), '{}'.format(body)])
+ if root: # If nohang was started by root
+ # send notification to all active users with special script
+ Popen(['/usr/sbin/nohang_notify_low_mem', '--mem', low_mem_percent,
+ '--pid', pid, '--name', name])
+ else: # Or by regular user
+ # send notification to user that runs this nohang
+ Popen(['notify-send', '--icon=dialog-warning',
+ 'Low memory: {}'.format(title), '{}'.format(body)])
def send_notify(signal, name, pid):
+ """
+ Notificate about OOM Preventing.
+
+ signal: key for notify_sig_dict
+ name: str process name
+ pid: str process pid
+ """
title = 'Preventing OOM'
body = '{} process {}, {}'.format(
notify_sig_dict[signal], pid, name.replace('&', '*'))
if root:
- # отправляем уведомление всем залогиненным пользователям
+ # send notification to all active users with notify-send
b = root_notify_env()
if len(b) > 0:
for i in b:
@@ -247,16 +293,23 @@ def send_notify(signal, name, pid):
dbus_env, 'notify-send', '--icon=dialog-warning',
'{}'.format(title), '{}'.format(body)])
else:
- # отправляем уведомление пользователю, который запустил nohang
+ # send notification to user that runs this nohang
Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)])
def send_notify_etc(pid, name, command):
+ """
+ Notificate about OOM Preventing.
+
+ command: str command that will be executed
+ name: str process name
+ pid: str process pid
+ """
title = 'Preventing OOM'
body = 'Victim is process {}, {}\nExecute the command:\n{}'.format(
pid, name.replace('&', '*'), command.replace('&', '*'))
if root:
- # отправляем уведомление всем залогиненным пользователям
+ # send notification to all active users with notify-send
b = root_notify_env()
if len(b) > 0:
for i in b:
@@ -265,11 +318,17 @@ def send_notify_etc(pid, name, command):
dbus_env, 'notify-send', '--icon=dialog-warning',
'{}'.format(title), '{}'.format(body)])
else:
- # отправляем уведомление пользователю, который запустил nohang
- Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)])
+ # send notification to user that runs this nohang
+ Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'
+ .format(body)])
def sleep_after_send_signal(signal):
+ """
+ Sleeping after signal was sent.
+
+ signal: sent signal
+ """
if signal is signal.SIGKILL:
if print_sleep_periods:
print(' sleep', min_delay_after_sigkill)
@@ -281,7 +340,11 @@ def sleep_after_send_signal(signal):
def find_victim_and_send_signal(signal):
+ """
+ Please describe this.
+ thanks
+ """
if decrease_oom_score_adj and root:
func_decrease_oom_score_adj(oom_score_adj_max)
@@ -322,23 +385,19 @@ def find_victim_and_send_signal(signal):
badness = 0
pid_badness_list.append((pid, badness))
-
- # получаем отсортированный по badness список пар (pid, badness)
+ # Make list of (pid, badness) tuples, sorted by 'badness' values
pid_tuple_list = sorted(
pid_badness_list, key=itemgetter(1), reverse=True)[0]
- # получаем максимальный badness
+ # Get maximum 'badness' value
victim_badness = pid_tuple_list[1]
- if victim_badness >= min_badness:
-
- # пытаемся отправить сигнал найденной жертве
+ if victim_badness >= min_badness: # Try to send signal to found victim
pid = pid_tuple_list[0]
-
name = pid_to_name(pid)
- # находим VmRSS и VmSwap процесса, которому попытаемся послать сигнал
+ # Get VmRSS and VmSwap of victim process and try to send signal
try:
with open('/proc/' + pid + '/status') as f:
for n, line in enumerate(f):
@@ -367,7 +426,12 @@ def find_victim_and_send_signal(signal):
command = etc_dict[name]
exit_status = os.system(etc_dict[name])
response_time = time() - time0
- etc_info = ' Finding the process with the highest badness\n Victim is {}, pid: {}, badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Execute the command: {}\n Exit status: {}; response time: {} ms'.format(name, pid, victim_badness, vm_rss, vm_swap, command, exit_status, round(response_time * 1000))
+ etc_info = ''' Finding the process with the highest badness\n
+ Victim is {}, pid:{}, badness:{}, VmRSS: {} MiB, VmSwap: {} MiB\n
+ Execute the command: {}\n
+ Exit status: {}; response time: {} ms'''.format(
+ name, pid, victim_badness, vm_rss, vm_swap, command,
+ exit_status, round(response_time * 1000))
print(mem_info)
print(etc_info)
if gui_notifications:
@@ -390,6 +454,7 @@ def find_victim_and_send_signal(signal):
response_time = time() - time0
send_result = 'no such process; response time: {} ms'.format(round(response_time * 1000))
+ # Pls correct line length =)
preventing_oom_message = ' Finding the process with the highest badness\n Victim is {}, pid: {}, badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Sending {} to the victim; {}'.format(name, pid, victim_badness, vm_rss, vm_swap, sig_dict[signal], send_result)
print(mem_info)
print(preventing_oom_message)
@@ -407,7 +472,7 @@ def find_victim_and_send_signal(signal):
def sleep_after_check_mem():
- # задание периода сна в зависимости от рейтов и уровней доступной памяти
+ """Specify sleep times depends on rates and avialable memory."""
t_mem = mem_available / rate_mem
t_swap = swap_free / rate_swap
t_zram = (mem_total - mem_used_zram) / rate_zram
@@ -429,8 +494,8 @@ def sleep_after_check_mem():
exit()
-
def fattest():
+ """Find the 'fattest' process"""
pid_badness_list = []
if regex_matching:
@@ -468,8 +533,7 @@ def fattest():
badness = 0
pid_badness_list.append((pid, badness))
-
- # получаем отсортированный по badness список пар (pid, badness)
+ # Make list of (pid, badness) tuples, sorted by 'badness' values
pid_tuple_list = sorted(
pid_badness_list, key=itemgetter(1), reverse=True)[0]
@@ -480,12 +544,10 @@ def fattest():
return (name, pid)
-
##########################################################################
# поиск позиций и mem_total
-
with open('/proc/meminfo') as file:
mem_list = file.readlines()
@@ -505,7 +567,7 @@ mem_total = int(mem_list[0].split(':')[1].strip(' kB\n'))
with open('/proc/self/status') as file:
status_list = file.readlines()
-# список имен из /proc/*/status для дальнейшего поиска позиций VmRSS and VmSwap
+# Get names from /proc/*/status to be able to get VmRSS and VmSwap values
status_names = []
for s in status_list:
status_names.append(s.split(':')[0])
@@ -515,9 +577,9 @@ vm_swap_index = status_names.index('VmSwap')
##########################################################################
-# получение пути к конфигу
+# Configurations
-# парсинг аргументов командной строки
+# Cmd argparse
parser = ArgumentParser()
parser.add_argument(
'-c',
@@ -541,7 +603,7 @@ if arg_config is None:
config = i
break
if config is None:
- print('По дефолтным путям конфиг не найден\n', conf_err_mess)
+ print('Default configuration was not found\n', conf_err_mess)
exit()
else:
@@ -625,7 +687,6 @@ 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'])
@@ -654,7 +715,7 @@ if 'niceness' in config_dict:
print('Invalid niceness value, not integer\nExit')
exit()
if niceness < -20 or niceness > 19:
- print('Недопустимое значение niceness\nExit')
+ print('niceness out of range [-20; 19]\nExit')
exit()
else:
print('niceness not in config\nExit')
@@ -668,7 +729,7 @@ if 'oom_score_adj' in config_dict:
print('Invalid oom_score_adj value, not integer\nExit')
exit()
if oom_score_adj < -1000 or oom_score_adj > 1000:
- print('Недопустимое значение oom_score_adj\nExit')
+ print('oom_score_adj out of range [-1000; 1000]\nExit')
exit()
else:
print('oom_score_adj not in config\nExit')
@@ -681,7 +742,7 @@ if 'rate_mem' in config_dict:
print('Invalid rate_mem value, not float\nExit')
exit()
if rate_mem <= 0:
- print('rate_mem должен быть положительным\nExit')
+ print('rate_mem MUST be > 0\nExit')
exit()
else:
print('rate_mem not in config\nExit')
@@ -694,7 +755,7 @@ if 'rate_swap' in config_dict:
print('Invalid rate_swap value, not float\nExit')
exit()
if rate_swap <= 0:
- print('rate_swap должен быть положительным\nExit')
+ print('rate_swap MUST be > 0\nExit')
exit()
else:
print('rate_swap not in config\nExit')
@@ -707,94 +768,149 @@ if 'rate_zram' in config_dict:
print('Invalid rate_zram value, not float\nExit')
exit()
if rate_zram <= 0:
- print('rate_zram должен быть положительным\nExit')
+ print('rate_zram MUST be > 0\nExit')
exit()
else:
print('rate_zram not in config\nExit')
exit()
-if 'mem_min_sigterm' in config_dict:
- mem_min_sigterm = config_dict['mem_min_sigterm']
+def calculate_percent(arg_key):
+ """
+ Calculate mem_min_KEY_percent.
- if mem_min_sigterm.endswith('%'):
- # отбрасываем процент, получаем число
- mem_min_sigterm_percent = mem_min_sigterm[:-1].strip()
- # далее флоат тест
- mem_min_sigterm_percent = string_to_float_convert_test(mem_min_sigterm_percent)
- if mem_min_sigterm_percent is None:
- print('Invalid mem_min_sigterm value, not float\nExit')
- exit()
- # окончательная валидация
- if mem_min_sigterm_percent < 0 or mem_min_sigterm_percent > 100:
- print('mem_min_sigterm, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit')
- exit()
+ Try use this one)
+ arg_key: str key for config_dict
+ returns int mem_min_percent or NoneType if got some error
+ """
+ global mem_total
+ global string_to_float_convert_test
+ global config_dict
- # mem_min_sigterm_percent это теперь чистое валидное флоат число процентов, можно переводить в кб
- mem_min_sigterm_kb = mem_min_sigterm_percent / 100 * mem_total
- mem_min_sigterm_mb = round(mem_min_sigterm_kb / 1024)
+ if arg_key in config_dict:
+ mem_min = config_dict[arg_key]
- elif mem_min_sigterm.endswith('M'):
- mem_min_sigterm_mb = string_to_float_convert_test(mem_min_sigterm[:-1].strip())
- if mem_min_sigterm_mb is None:
- print('Invalid mem_min_sigterm value, not float\nExit')
- exit()
- mem_min_sigterm_kb = mem_min_sigterm_mb * 1024
- if mem_min_sigterm_kb > mem_total:
- print('mem_min_sigterm value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
- exit()
- mem_min_sigterm_percent = mem_min_sigterm_kb / mem_total * 100
+ if mem_min.endswith('%'):
+ # truncate percents, so we have a number
+ mem_min_percent = mem_min[:-1].strip()
+ # then 'float test'
+ mem_min_percent = string_to_float_convert_test(mem_min_percent)
+ if mem_min_percent is None:
+ print('Invalid {} value, not float\nExit'.format(arg_key))
+ exit()
+ # Final validations...
+ if mem_min_percent < 0 or mem_min_percent > 100:
+ print('{}, as percents value, out of range [0; 100]\nExit'.format(arg_key))
+ exit()
+
+ # mem_min_sigterm_percent is clean and valid float percentage. Can translate into Kb
+ mem_min_kb = mem_min_percent / 100 * mem_total
+ mem_min_mb = round(mem_min_sigterm_kb / 1024)
+
+ elif mem_min.endswith('M'):
+ mem_min_mb = string_to_float_convert_test(mem_min[:-1].strip())
+ if mem_min_mb is None:
+ print('Invalid {} value, not float\nExit'.format(arg_key))
+ exit()
+ mem_min_kb = mem_min_mb * 1024
+ if mem_min_kb > mem_total:
+ print('{} value can not be greater then MemTotal ({} MiB)\nExit'.format(arg_key, round(mem_total / 1024)))
+ exit()
+ mem_min_percent = mem_min_kb / mem_total * 100
+
+ else:
+ print('Invalid {} units in config.\n Exit'.format(arg_key))
+ mem_min_percent = None
else:
- print('Конфиг инвалид, для mem_min_sigterm неверно указаны единицы измерения\nExit')
- exit()
+ print('{} not in config\nExit'.format(arg_key))
+ mem_min_percent = None
-else:
- print('mem_min_sigterm not in config\nExit')
- exit()
+ return mem_min_percent
-if 'mem_min_sigkill' in config_dict:
- mem_min_sigkill = config_dict['mem_min_sigkill']
+# if 'mem_min_sigterm' in config_dict:
+# mem_min_sigterm = config_dict['mem_min_sigterm']
- if mem_min_sigkill.endswith('%'):
- # отбрасываем процент, получаем число
- mem_min_sigkill_percent = mem_min_sigkill[:-1].strip()
- # далее флоат тест
- mem_min_sigkill_percent = string_to_float_convert_test(mem_min_sigkill_percent)
- if mem_min_sigkill_percent is None:
- print('Invalid mem_min_sigkill value, not float\nExit')
- exit()
- # окончательная валидация
- if mem_min_sigkill_percent < 0 or mem_min_sigkill_percent > 100:
- print('mem_min_sigkill, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit')
- exit()
+# if mem_min_sigterm.endswith('%'):
+# # truncate percents, so we have a number
+# mem_min_sigterm_percent = mem_min_sigterm[:-1].strip()
+# # then 'float test'
+# mem_min_sigterm_percent = string_to_float_convert_test(mem_min_sigterm_percent)
+# if mem_min_sigterm_percent is None:
+# print('Invalid mem_min_sigterm value, not float\nExit')
+# exit()
+# # Final validations...
+# if mem_min_sigterm_percent < 0 or mem_min_sigterm_percent > 100:
+# print('mem_min_sigterm, as percents value, out of range [0; 100]\nExit')
+# exit()
- # mem_min_sigterm_percent это теперь чистое валидное флоат число процентов, можно переводить в кб
- mem_min_sigkill_kb = mem_min_sigkill_percent / 100 * mem_total
- mem_min_sigkill_mb = round(mem_min_sigkill_kb / 1024)
+# # mem_min_sigterm_percent is clean and valid float percentage. Can translate into Kb
+# mem_min_sigterm_kb = mem_min_sigterm_percent / 100 * mem_total
+# mem_min_sigterm_mb = round(mem_min_sigterm_kb / 1024)
- elif mem_min_sigkill.endswith('M'):
- mem_min_sigkill_mb = string_to_float_convert_test(mem_min_sigkill[:-1].strip())
- if mem_min_sigkill_mb is None:
- print('Invalid mem_min_sigkill value, not float\nExit')
- exit()
- mem_min_sigkill_kb = mem_min_sigkill_mb * 1024
- if mem_min_sigkill_kb > mem_total:
- print('mem_min_sigkill value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
- exit()
- mem_min_sigkill_percent = mem_min_sigkill_kb / mem_total * 100
+# elif mem_min_sigterm.endswith('M'):
+# mem_min_sigterm_mb = string_to_float_convert_test(mem_min_sigterm[:-1].strip())
+# if mem_min_sigterm_mb is None:
+# print('Invalid mem_min_sigterm value, not float\nExit')
+# exit()
+# mem_min_sigterm_kb = mem_min_sigterm_mb * 1024
+# if mem_min_sigterm_kb > mem_total:
+# print('mem_min_sigterm value can not be greater then MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
+# exit()
+# mem_min_sigterm_percent = mem_min_sigterm_kb / mem_total * 100
- else:
- print('Конфиг инвалид, для mem_min_sigkill неверно указаны единицы измерения\nExit')
- exit()
+# else:
+# print('Invalid mem_min_sigterm units in config.\n Exit')
+# exit()
-else:
- print('mem_min_sigkill not in config\nExit')
- exit()
+# else:
+# print('mem_min_sigterm not in config\nExit')
+# exit()
+# if 'mem_min_sigkill' in config_dict:
+# mem_min_sigkill = config_dict['mem_min_sigkill']
+# if mem_min_sigkill.endswith('%'):
+# # truncate percent, so we have a number
+# mem_min_sigkill_percent = mem_min_sigkill[:-1].strip()
+# # then 'float test'
+# mem_min_sigkill_percent = string_to_float_convert_test(mem_min_sigkill_percent)
+# if mem_min_sigkill_percent is None:
+# print('Invalid mem_min_sigkill value, not float\nExit')
+# exit()
+# # Final validation
+# if mem_min_sigkill_percent < 0 or mem_min_sigkill_percent > 100:
+# print('mem_min_sigkill, as a percentage, out of range [0; 100]\nExit')
+# exit()
+
+# # mem_min_sigterm_percent is clean and valid float percentage. Can translate into Kb
+# mem_min_sigkill_kb = mem_min_sigkill_percent / 100 * mem_total
+# mem_min_sigkill_mb = round(mem_min_sigkill_kb / 1024)
+
+# elif mem_min_sigkill.endswith('M'):
+# mem_min_sigkill_mb = string_to_float_convert_test(mem_min_sigkill[:-1].strip())
+# if mem_min_sigkill_mb is None:
+# print('Invalid mem_min_sigkill value, not float\nExit')
+# exit()
+# mem_min_sigkill_kb = mem_min_sigkill_mb * 1024
+# if mem_min_sigkill_kb > mem_total:
+# print('mem_min_sigkill value can not be greater then MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
+# exit()
+# mem_min_sigkill_percent = mem_min_sigkill_kb / mem_total * 100
+
+# else:
+# print('Invalid mem_min_sigkill units in config\nExit')
+# exit()
+
+# else:
+# print('mem_min_sigkill not in config\nExit')
+# exit()
+
+
+mem_min_sigterm_percent = calculate_percent('mem_min_sigterm')
+mem_min_sigkill_percent = calculate_percent('mem_min_sigkill')
# НУЖНА ВАЛИДАЦИЯ НА МЕСТЕ!
if 'swap_min_sigterm' in config_dict:
@@ -812,84 +928,87 @@ else:
exit()
-if 'zram_max_sigterm' in config_dict:
- zram_max_sigterm = config_dict['zram_max_sigterm']
+zram_max_sigterm_percent = calculate_percent('zram_max_sigterm')
+zram_max_sigkill_percent = calculate_percent('zram_max_sigkill')
- if zram_max_sigterm.endswith('%'):
- # отбрасываем процент, получаем число
- zram_max_sigterm_percent = zram_max_sigterm[:-1].strip()
- # далее флоат тест
- zram_max_sigterm_percent = string_to_float_convert_test(zram_max_sigterm_percent)
- if zram_max_sigterm_percent is None:
- print('Invalid zram_max_sigterm value, not float\nExit')
- exit()
- # окончательная валидация
- if zram_max_sigterm_percent < 0 or zram_max_sigterm_percent > 100:
- print('zram_max_sigterm, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit')
- exit()
+# if 'zram_max_sigterm' in config_dict:
+# zram_max_sigterm = config_dict['zram_max_sigterm']
- # zram_max_sigterm_percent это теперь чистое валидное флоат число процентов, можно переводить в кб
- zram_max_sigterm_kb = zram_max_sigterm_percent / 100 * mem_total
- zram_max_sigterm_mb = round(zram_max_sigterm_kb / 1024)
+# if zram_max_sigterm.endswith('%'):
+# # отбрасываем процент, получаем число
+# zram_max_sigterm_percent = zram_max_sigterm[:-1].strip()
+# # далее флоат тест
+# zram_max_sigterm_percent = string_to_float_convert_test(zram_max_sigterm_percent)
+# if zram_max_sigterm_percent is None:
+# print('Invalid zram_max_sigterm value, not float\nExit')
+# exit()
+# # окончательная валидация
+# if zram_max_sigterm_percent < 0 or zram_max_sigterm_percent > 100:
+# print('zram_max_sigterm, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit')
+# exit()
- elif zram_max_sigterm.endswith('M'):
- zram_max_sigterm_mb = string_to_float_convert_test(zram_max_sigterm[:-1].strip())
- if zram_max_sigterm_mb is None:
- print('Invalid zram_max_sigterm value, not float\nExit')
- exit()
- zram_max_sigterm_kb = zram_max_sigterm_mb * 1024
- if zram_max_sigterm_kb > mem_total:
- print('zram_max_sigterm value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
- exit()
- zram_max_sigterm_percent = zram_max_sigterm_kb / mem_total * 100
+# # zram_max_sigterm_percent это теперь чистое валидное флоат число процентов, можно переводить в кб
+# zram_max_sigterm_kb = zram_max_sigterm_percent / 100 * mem_total
+# zram_max_sigterm_mb = round(zram_max_sigterm_kb / 1024)
- else:
- print('Конфиг инвалид, для zram_max_sigterm неверно указаны единицы измерения\nExit')
- exit()
+# elif zram_max_sigterm.endswith('M'):
+# zram_max_sigterm_mb = string_to_float_convert_test(zram_max_sigterm[:-1].strip())
+# if zram_max_sigterm_mb is None:
+# print('Invalid zram_max_sigterm value, not float\nExit')
+# exit()
+# zram_max_sigterm_kb = zram_max_sigterm_mb * 1024
+# if zram_max_sigterm_kb > mem_total:
+# print('zram_max_sigterm value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
+# exit()
+# zram_max_sigterm_percent = zram_max_sigterm_kb / mem_total * 100
-else:
- print('zram_max_sigterm not in config\nExit')
- exit()
+# else:
+# print('Конфиг инвалид, для zram_max_sigterm неверно указаны единицы измерения\nExit')
+# exit()
+
+# else:
+# print('zram_max_sigterm not in config\nExit')
+# exit()
-if 'zram_max_sigkill' in config_dict:
- zram_max_sigkill = config_dict['zram_max_sigkill']
+# if 'zram_max_sigkill' in config_dict:
+# zram_max_sigkill = config_dict['zram_max_sigkill']
- if zram_max_sigkill.endswith('%'):
- # отбрасываем процент, получаем число
- zram_max_sigkill_percent = zram_max_sigkill[:-1].strip()
- # далее флоат тест
- zram_max_sigkill_percent = string_to_float_convert_test(zram_max_sigkill_percent)
- if zram_max_sigkill_percent is None:
- print('Invalid zram_max_sigkill value, not float\nExit')
- exit()
- # окончательная валидация
- if zram_max_sigkill_percent < 0 or zram_max_sigkill_percent > 100:
- print('zram_max_sigkill, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit')
- exit()
+# if zram_max_sigkill.endswith('%'):
+# # отбрасываем процент, получаем число
+# zram_max_sigkill_percent = zram_max_sigkill[:-1].strip()
+# # далее флоат тест
+# zram_max_sigkill_percent = string_to_float_convert_test(zram_max_sigkill_percent)
+# if zram_max_sigkill_percent is None:
+# print('Invalid zram_max_sigkill value, not float\nExit')
+# exit()
+# # окончательная валидация
+# if zram_max_sigkill_percent < 0 or zram_max_sigkill_percent > 100:
+# print('zram_max_sigkill, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit')
+# exit()
- # zram_max_sigkill_percent это теперь чистое валидное флоат число процентов, можно переводить в кб
- zram_max_sigkill_kb = zram_max_sigkill_percent / 100 * mem_total
- zram_max_sigkill_mb = round(zram_max_sigkill_kb / 1024)
+# # zram_max_sigkill_percent это теперь чистое валидное флоат число процентов, можно переводить в кб
+# zram_max_sigkill_kb = zram_max_sigkill_percent / 100 * mem_total
+# zram_max_sigkill_mb = round(zram_max_sigkill_kb / 1024)
- elif zram_max_sigkill.endswith('M'):
- zram_max_sigkill_mb = string_to_float_convert_test(zram_max_sigkill[:-1].strip())
- if zram_max_sigkill_mb is None:
- print('Invalid zram_max_sigkill value, not float\nExit')
- exit()
- zram_max_sigkill_kb = zram_max_sigkill_mb * 1024
- if zram_max_sigkill_kb > mem_total:
- print('zram_max_sigkill value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
- exit()
- zram_max_sigkill_percent = zram_max_sigkill_kb / mem_total * 100
+# elif zram_max_sigkill.endswith('M'):
+# zram_max_sigkill_mb = string_to_float_convert_test(zram_max_sigkill[:-1].strip())
+# if zram_max_sigkill_mb is None:
+# print('Invalid zram_max_sigkill value, not float\nExit')
+# exit()
+# zram_max_sigkill_kb = zram_max_sigkill_mb * 1024
+# if zram_max_sigkill_kb > mem_total:
+# print('zram_max_sigkill value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
+# exit()
+# zram_max_sigkill_percent = zram_max_sigkill_kb / mem_total * 100
- else:
- print('Конфиг инвалид, для zram_max_sigkill неверно указаны единицы измерения\nExit')
- exit()
+# else:
+# print('Конфиг инвалид, для zram_max_sigkill неверно указаны единицы измерения\nExit')
+# exit()
-else:
- print('zram_max_sigkill not in config\nExit')
- exit()
+# else:
+# print('zram_max_sigkill not in config\nExit')
+# exit()
if 'min_delay_after_sigterm' in config_dict:
@@ -951,7 +1070,6 @@ else:
exit()
-
regex_matching = conf_parse_bool('regex_matching')
@@ -987,13 +1105,11 @@ else:
exit()
-
gui_low_memory_warnings = conf_parse_bool('gui_low_memory_warnings')
gui_notifications = conf_parse_bool('gui_notifications')
-
if 'min_time_between_warnings' in config_dict:
min_time_between_warnings = string_to_float_convert_test(
config_dict['min_time_between_warnings'])
@@ -1008,45 +1124,46 @@ else:
exit()
-if 'mem_min_warnings' in config_dict:
- mem_min_warnings = config_dict['mem_min_warnings']
+mem_min_warnings_percent = calculate_percent('mem_min_warnings')
- if mem_min_warnings.endswith('%'):
- # отбрасываем процент, получаем число
- mem_min_warnings_percent = mem_min_warnings[:-1].strip()
- # далее флоат тест
- mem_min_warnings_percent = string_to_float_convert_test(mem_min_warnings_percent)
- if mem_min_warnings_percent is None:
- print('Invalid mem_min_warnings value, not float\nExit')
- exit()
- # окончательная валидация
- if mem_min_warnings_percent < 0 or mem_min_warnings_percent > 100:
- print('mem_min_warnings, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit')
- exit()
+# if 'mem_min_warnings' in config_dict:
+# mem_min_warnings = config_dict['mem_min_warnings']
- # mem_min_warnings_percent это теперь чистое валидное флоат число процентов, можно переводить в кб
- mem_min_warnings_kb = mem_min_warnings_percent / 100 * mem_total
- mem_min_warnings_mb = round(mem_min_warnings_kb / 1024)
+# if mem_min_warnings.endswith('%'):
+# # отбрасываем процент, получаем число
+# mem_min_warnings_percent = mem_min_warnings[:-1].strip()
+# # далее флоат тест
+# mem_min_warnings_percent = string_to_float_convert_test(mem_min_warnings_percent)
+# if mem_min_warnings_percent is None:
+# print('Invalid mem_min_warnings value, not float\nExit')
+# exit()
+# # окончательная валидация
+# if mem_min_warnings_percent < 0 or mem_min_warnings_percent > 100:
+# print('mem_min_warnings, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit')
+# exit()
- elif mem_min_warnings.endswith('M'):
- mem_min_warnings_mb = string_to_float_convert_test(mem_min_warnings[:-1].strip())
- if mem_min_warnings_mb is None:
- print('Invalid mem_min_warnings value, not float\nExit')
- exit()
- mem_min_warnings_kb = mem_min_warnings_mb * 1024
- if mem_min_warnings_kb > mem_total:
- print('mem_min_warnings value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
- exit()
- mem_min_warnings_percent = mem_min_warnings_kb / mem_total * 100
+# # mem_min_warnings_percent это теперь чистое валидное флоат число процентов, можно переводить в кб
+# mem_min_warnings_kb = mem_min_warnings_percent / 100 * mem_total
+# mem_min_warnings_mb = round(mem_min_warnings_kb / 1024)
- else:
- print('Конфиг инвалид, для mem_min_warnings неверно указаны единицы измерения\nExit')
- exit()
+# elif mem_min_warnings.endswith('M'):
+# mem_min_warnings_mb = string_to_float_convert_test(mem_min_warnings[:-1].strip())
+# if mem_min_warnings_mb is None:
+# print('Invalid mem_min_warnings value, not float\nExit')
+# exit()
+# mem_min_warnings_kb = mem_min_warnings_mb * 1024
+# if mem_min_warnings_kb > mem_total:
+# print('mem_min_warnings value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
+# exit()
+# mem_min_warnings_percent = mem_min_warnings_kb / mem_total * 100
-else:
- print('mem_min_warnings not in config\nExit')
- exit()
+# else:
+# print('Конфиг инвалид, для mem_min_warnings неверно указаны единицы измерения\nExit')
+# exit()
+# else:
+# print('mem_min_warnings not in config\nExit')
+# exit()
# НА МЕСТЕ!!!
@@ -1057,45 +1174,46 @@ else:
exit()
+zram_max_warnings_percent = calculate_percent('zram_max_warnings..')
-if 'zram_max_warnings' in config_dict:
- zram_max_warnings = config_dict['zram_max_warnings']
+# if 'zram_max_warnings' in config_dict:
+# zram_max_warnings = config_dict['zram_max_warnings']
- if zram_max_warnings.endswith('%'):
- # отбрасываем процент, получаем число
- zram_max_warnings_percent = zram_max_warnings[:-1].strip()
- # далее флоат тест
- zram_max_warnings_percent = string_to_float_convert_test(zram_max_warnings_percent)
- if zram_max_warnings_percent is None:
- print('Invalid zram_max_warnings value, not float\nExit')
- exit()
- # окончательная валидация
- if zram_max_warnings_percent < 0 or zram_max_warnings_percent > 100:
- print('zram_max_warnings, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit')
- exit()
+# if zram_max_warnings.endswith('%'):
+# # отбрасываем процент, получаем число
+# zram_max_warnings_percent = zram_max_warnings[:-1].strip()
+# # далее флоат тест
+# zram_max_warnings_percent = string_to_float_convert_test(zram_max_warnings_percent)
+# if zram_max_warnings_percent is None:
+# print('Invalid zram_max_warnings value, not float\nExit')
+# exit()
+# # окончательная валидация
+# if zram_max_warnings_percent < 0 or zram_max_warnings_percent > 100:
+# print('zram_max_warnings, выраженный в процентах, должен быть быть в диапазоне [0; 100]\nExit')
+# exit()
- # zram_max_warnings_percent это теперь чистое валидное флоат число процентов, можно переводить в кб
- zram_max_warnings_kb = zram_max_warnings_percent / 100 * mem_total
- zram_max_warnings_mb = round(zram_max_warnings_kb / 1024)
+# # zram_max_warnings_percent это теперь чистое валидное флоат число процентов, можно переводить в кб
+# zram_max_warnings_kb = zram_max_warnings_percent / 100 * mem_total
+# zram_max_warnings_mb = round(zram_max_warnings_kb / 1024)
- elif zram_max_warnings.endswith('M'):
- zram_max_warnings_mb = string_to_float_convert_test(zram_max_warnings[:-1].strip())
- if zram_max_warnings_mb is None:
- print('Invalid zram_max_warnings value, not float\nExit')
- exit()
- zram_max_warnings_kb = zram_max_warnings_mb * 1024
- if zram_max_warnings_kb > mem_total:
- print('zram_max_warnings value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
- exit()
- zram_max_warnings_percent = zram_max_warnings_kb / mem_total * 100
+# elif zram_max_warnings.endswith('M'):
+# zram_max_warnings_mb = string_to_float_convert_test(zram_max_warnings[:-1].strip())
+# if zram_max_warnings_mb is None:
+# print('Invalid zram_max_warnings value, not float\nExit')
+# exit()
+# zram_max_warnings_kb = zram_max_warnings_mb * 1024
+# if zram_max_warnings_kb > mem_total:
+# print('zram_max_warnings value не должен быть больше MemTotal ({} MiB)\nExit'.format(round(mem_total / 1024)))
+# exit()
+# zram_max_warnings_percent = zram_max_warnings_kb / mem_total * 100
- else:
- print('Конфиг инвалид, для zram_max_warnings неверно указаны единицы измерения\nExit')
- exit()
+# else:
+# print('Конфиг инвалид, для zram_max_warnings неверно указаны единицы измерения\nExit')
+# exit()
-else:
- print('zram_max_warnings not in config\nExit')
- exit()
+# else:
+# print('zram_max_warnings not in config\nExit')
+# exit()
execute_the_command = conf_parse_bool('execute_the_command')
@@ -1151,7 +1269,7 @@ else:
##########################################################################
-# self-defense
+# self-defense
# повышаем приоритет
try:
@@ -1189,7 +1307,6 @@ self_uid = os.geteuid()
self_pid = os.getpid()
-
if self_uid == 0:
root = True
decrease_res = 'OK'
@@ -1198,7 +1315,6 @@ else:
decrease_res = 'Impossible'
-
if root and realtime_ionice:
os.system('ionice -c 1 -n {} -p {}'.format(
realtime_ionice_classdata, self_pid))
@@ -1209,7 +1325,6 @@ if root and realtime_ionice:
if print_config:
-
print('\n1. Memory levels to respond to as an OOM threat\n[displaying these options need fix]\n')
print('mem_min_sigterm: {} MiB, {} %'.format(
@@ -1225,13 +1340,11 @@ if print_config:
print('zram_max_sigkill: {} MiB, {} %'.format(
round(zram_max_sigkill_mb), round(zram_max_sigkill_percent, 1)))
-
print('\n2. The frequency of checking the level of available memory (and CPU usage)\n')
print('rate_mem: {}'.format(rate_mem))
print('rate_swap: {}'.format(rate_swap))
print('rate_zram: {}'.format(rate_zram))
-
print('\n3. The prevention of killing innocent victims\n')
print('min_delay_after_sigterm: {}'.format(min_delay_after_sigterm))
print('min_delay_after_sigkill: {}'.format(min_delay_after_sigkill))
@@ -1244,7 +1357,6 @@ if print_config:
if decrease_oom_score_adj:
print('oom_score_adj_max: {}'.format(oom_score_adj_max))
-
print('\n4. Impact on the badness of processes via matching their names\nwith regular expressions\n')
print('regex_matching: {}'.format(regex_matching))
if regex_matching:
@@ -1253,7 +1365,6 @@ if print_config:
print('avoid_regex: {}'.format(avoid_regex))
print('avoid_factor: {}'.format(avoid_factor))
-
print('\n5. The execution of a specific command instead of sending the\nSIGTERM signal\n')
print('execute_the_command: {}'.format(execute_the_command))
if execute_the_command:
@@ -1261,7 +1372,6 @@ if print_config:
for key in etc_dict:
print('{} {}'.format(key.ljust(15), etc_dict[key]))
-
print('\n6. GUI notifications:\n- OOM prevention results and\n- low memory warnings\n')
print('gui_notifications: {}'.format(gui_notifications))
@@ -1277,7 +1387,6 @@ if print_config:
print('zram_max_warnings: {} MiB, {} %'.format(
round(zram_max_warnings_mb), round(zram_max_warnings_percent, 1)))
-
print('\n7. Preventing the slowing down of the program\n[displaying these options need fix]\n')
print('mlockall: {} ({})'.format(mlockall, mla_res))
print('niceness: {} ({})'.format(
@@ -1308,7 +1417,7 @@ mem_len = len(str(round(mem_total / 1024.0)))
if gui_notifications or gui_low_memory_warnings:
from subprocess import Popen, PIPE
notify_sig_dict = {signal.SIGKILL: 'Killing',
- signal.SIGTERM: 'Terminating'}
+ signal.SIGTERM: 'Terminating'}
if regex_matching:
@@ -1328,11 +1437,6 @@ print('Monitoring started!')
##########################################################################
-
-
-
-
-
while True:
# find mem_available, swap_total, swap_free
@@ -1348,8 +1452,6 @@ while True:
swap_free = int(line.split(':')[1].strip(' kB\n'))
break
-
-
# if swap_min_sigkill is set in percent
if swap_kill_is_percent:
swap_min_sigkill_kb = swap_total * swap_min_sigkill_percent / 100.0
@@ -1360,7 +1462,6 @@ while True:
if swap_warn_is_percent:
swap_min_warnings_kb = swap_total * swap_min_warnings_percent / 100.0
-
# find MemUsedZram
disksize_sum = 0
mem_used_total_sum = 0
@@ -1373,7 +1474,6 @@ while True:
mem_used_total_sum + disksize_sum * zram_disksize_factor
) / 1024.0
-
if print_mem_check_results:
# для рассчета ширины столбца свопа
@@ -1393,15 +1493,14 @@ while True:
just_percent_swap(swap_free / (swap_total + 0.1))))
else:
- print('MemAvail: {} M, {} % | SwapFree: {} M, {} % | Mem' \
- 'UsedZram: {} M, {} %'.format(
- human(mem_available, mem_len),
- just_percent_mem(mem_available / mem_total),
- human(swap_free, swap_len),
- just_percent_swap(swap_free / (swap_total + 0.1)),
- human(mem_used_zram, mem_len),
- just_percent_mem(mem_used_zram / mem_total)))
-
+ print('MemAvail: {} M, {} % | SwapFree: {} M, {} % | Mem'
+ 'UsedZram: {} M, {} %'.format(
+ human(mem_available, mem_len),
+ just_percent_mem(mem_available / mem_total),
+ human(swap_free, swap_len),
+ just_percent_swap(swap_free / (swap_total + 0.1)),
+ human(mem_used_zram, mem_len),
+ just_percent_mem(mem_used_zram / mem_total)))
# если swap_min_sigkill задан в абсолютной величине и Swap_total = 0
if swap_total > swap_min_sigkill_kb:
@@ -1416,9 +1515,6 @@ while True:
# СТОИТ ПЕЧАТАТЬ СВОП ТОЛЬКО ПРИ SwapTotal > 0
swap_sigterm_pc = '-'
-
-
-
# проверка превышения порогов
# порог превышен - пытаемся предотвратить OOM
# пороги не превышены - спим
@@ -1429,16 +1525,16 @@ while True:
mem_info = 'Low memory; corrective action required!\n MemAvailable [{} MiB, {} %] <= mem_min_sigkill [{} MiB, {} %]\n Swa' \
'pFree [{} MiB, {} %] <= swap_min_sigkill [{} MiB, {} %]'.format(
- kib_to_mib(mem_available),
- percent(mem_available / mem_total),
+ kib_to_mib(mem_available),
+ percent(mem_available / mem_total),
- kib_to_mib(mem_min_sigkill_kb),
- percent(mem_min_sigkill_kb / mem_total),
+ kib_to_mib(mem_min_sigkill_kb),
+ percent(mem_min_sigkill_kb / mem_total),
- kib_to_mib(swap_free),
- percent(swap_free / (swap_total + 0.1)),
+ kib_to_mib(swap_free),
+ percent(swap_free / (swap_total + 0.1)),
- kib_to_mib(swap_min_sigkill_kb),
+ kib_to_mib(swap_min_sigkill_kb),
swap_sigkill_pc)
find_victim_and_send_signal(signal.SIGKILL)
@@ -1457,25 +1553,25 @@ while True:
# MEM SWAP TERM
elif mem_available <= mem_min_sigterm_kb and swap_free <= swap_min_sigterm_kb:
-
+
time0 = time()
mem_info = 'Low memory; corrective action required!\n MemAvailable [{} MiB, {} %] <= mem_min_sigterm [{} MiB, {} %]\n Sw' \
'apFree [{} MiB, {} %] <= swap_min_sigterm [{} MiB, {} %]'.format(
kib_to_mib(mem_available),
percent(mem_available / mem_total),
-
-
+
+
kib_to_mib(mem_min_sigterm_kb),
#percent(mem_min_sigterm_kb / mem_total),
-
+
# ОКРУГЛЯТЬ НА МЕСТЕ ВЫШЕ
round(mem_min_sigterm_percent, 1),
-
+
kib_to_mib(swap_free),
percent(swap_free / (swap_total + 0.1)),
-
-
+
+
kib_to_mib(swap_min_sigterm_kb),
swap_sigterm_pc)
@@ -1487,9 +1583,9 @@ while True:
mem_info = 'Low memory; corrective action required!\n MemUsedZram [{} MiB, {} %] >= zram_max_sigter' \
'm [{} M, {} %]'.format(
- kib_to_mib(mem_used_zram),
- percent(mem_used_zram / mem_total),
- kib_to_mib(zram_max_sigterm_kb),
+ kib_to_mib(mem_used_zram),
+ percent(mem_used_zram / mem_total),
+ kib_to_mib(zram_max_sigterm_kb),
percent(zram_max_sigterm_kb / mem_total))
find_victim_and_send_signal(signal.SIGTERM)
@@ -1506,10 +1602,12 @@ while True:
warn_timer = 0
sleep_after_check_mem()
-
# SLEEP BETWEEN MEM CHECKS
else:
stdout.flush()
sleep_after_check_mem()
+_check_mem()
+em()
+_check_mem()