new re syntax

This commit is contained in:
Alexey Avramov 2018-12-12 21:40:37 +09:00
parent c5285b8cc4
commit f79de3bb52
2 changed files with 59 additions and 220 deletions

232
nohang
View File

@ -326,7 +326,10 @@ def sleep_after_send_signal(signal):
def fattest(): def fattest():
"""Find the 'fattest' process, return pid and badness""" """
Find the process with highest badness and its badness adjustment
Return pid and badness
"""
pid_badness_list = [] pid_badness_list = []
@ -346,45 +349,30 @@ def fattest():
if regex_matching: if regex_matching:
name = pid_to_name(pid) name = pid_to_name(pid)
for re_tup in processname_re_list:
if search(avoid_regex, name) is not None: if search(re_tup[1], name) is not None:
if pid_to_cmdline(pid) == '': if pid_to_cmdline(pid) == '':
# skip kthreads # skip kthreads
continue continue
badness = int(badness / avoid_factor) badness += int(re_tup[0])
if search(prefer_regex, name) is not None:
if pid_to_cmdline(pid) == '':
# skip kthreads
continue
badness = int((badness + 1) * prefer_factor)
if re_match_cmdline: if re_match_cmdline:
cmdline = pid_to_cmdline(pid) cmdline = pid_to_cmdline(pid)
if cmdline == '': if cmdline == '':
# skip kthreads # skip kthreads
continue continue
for re_tup in cmdline_re_list:
if search(avoid_re_cmdline, cmdline) is not None: if search(re_tup[1], cmdline) is not None:
badness = int(badness / avoid_cmd_factor) badness += int(re_tup[0])
if search(prefer_re_cmdline, cmdline) is not None:
badness = int((badness + 1) * prefer_cmd_factor)
if re_match_uid: if re_match_uid:
uid = pid_to_uid(pid) uid = pid_to_uid(pid)
for re_tup in uid_re_list:
if search(avoid_re_uid, uid) is not None: if search(re_tup[1], uid) is not None:
if pid_to_cmdline(pid) == '': if pid_to_cmdline(pid) == '':
# skip kthreads # skip kthreads
continue continue
badness = int(badness / avoid_uid_factor) badness += int(re_tup[0])
if search(prefer_re_uid, uid) is not None:
if pid_to_cmdline(pid) == '':
# skip kthreads
continue
badness = int((badness + 1) * prefer_uid_factor)
except FileNotFoundError: except FileNotFoundError:
continue continue
@ -760,8 +748,14 @@ try:
# dictionary with config options # dictionary with config options
config_dict = dict() config_dict = dict()
processname_re_list = []
cmdline_re_list = []
uid_re_list = []
# dictionary with names and commands for the parameter # dictionary with names and commands for the parameter
# execute_the_command # execute_the_command
# тут тоже список нужен, а не словарь
etc_dict = dict() etc_dict = dict()
for line in f: for line in f:
@ -787,6 +781,21 @@ try:
exit() exit()
etc_dict[etc_name] = etc_command etc_dict[etc_name] = etc_command
# NEED VALIDATION!
if line.startswith('@PROCESSNAME_RE'):
a = line.partition('@PROCESSNAME_RE')[2].strip(' \n').partition('///')
processname_re_list.append((a[0].strip(' '), a[2].strip(' ')))
if line.startswith('@CMDLINE_RE'):
a = line.partition('@CMDLINE_RE')[2].strip(' \n').partition('///')
cmdline_re_list.append((a[0].strip(' '), a[2].strip(' ')))
if line.startswith('@UID_RE'):
a = line.partition('@UID_RE')[2].strip(' \n').partition('///')
uid_re_list.append((a[0].strip(' '), a[2].strip(' ')))
except PermissionError: except PermissionError:
print('PermissionError', conf_err_mess) print('PermissionError', conf_err_mess)
exit() exit()
@ -800,6 +809,9 @@ except IndexError:
print('IndexError', conf_err_mess) print('IndexError', conf_err_mess)
exit() exit()
# print(processname_re_list)
# print(cmdline_re_list)
# print(uid_re_list)
########################################################################## ##########################################################################
@ -824,168 +836,10 @@ re_match_cmdline = conf_parse_bool('re_match_cmdline')
re_match_uid = conf_parse_bool('re_match_uid') re_match_uid = conf_parse_bool('re_match_uid')
if regex_matching or re_match_cmdline or re_match_uid: if regex_matching or re_match_cmdline or re_match_uid:
from re import search from re import search
import sre_constants import sre_constants
prefer_regex = conf_parse_string('prefer_regex')
if prefer_regex == '':
print('Invalid prefer_regex value, '
'regex pattern must not be empty')
exit()
# RE pattern validation
try:
search(prefer_regex, '')
except sre_constants.error:
print('Invalid prefer_regex value, '
'invalid RE pattern: {}'.format(prefer_regex))
exit()
avoid_regex = conf_parse_string('avoid_regex')
if avoid_regex == '':
print('Invalid avoid_regex value, '
'regex pattern must not be empty')
exit()
# RE pattern validation
try:
search(avoid_regex, '')
except sre_constants.error:
print('Invalid avoid_regex value, '
'invalid RE pattern: {}'.format(avoid_regex))
exit()
prefer_re_cmdline = conf_parse_string('prefer_re_cmdline')
if prefer_re_cmdline == '':
print('Invalid prefer_re_cmdline value, '
'regex pattern must not be empty')
exit()
# RE pattern validation
try:
search(prefer_re_cmdline, '')
except sre_constants.error:
print('Invalid prefer_re_cmdline value, '
'invalid RE pattern: {}'.format(prefer_re_cmdline))
exit()
avoid_re_cmdline = conf_parse_string('avoid_re_cmdline')
if avoid_re_cmdline == '':
print('Invalid avoid_re_cmdline value, '
'regex pattern must not be empty')
exit()
# RE pattern validation
try:
search(avoid_re_cmdline, '')
except sre_constants.error:
print('Invalid avoid_re_cmdline value, '
'invalid RE pattern: {}'.format(avoid_re_cmdline))
exit()
prefer_re_uid = conf_parse_string('prefer_re_uid')
if prefer_re_uid == '':
print('Invalid prefer_re_uid value, '
'regex pattern must not be empty')
exit()
# RE pattern validation
try:
search(prefer_re_uid, '')
except sre_constants.error:
print('Invalid prefer_re_uid value, '
'invalid RE pattern: {}'.format(prefer_re_uid))
exit()
avoid_re_uid = conf_parse_string('avoid_re_uid')
if avoid_re_uid == '':
print('Invalid avoid_re_uid value, '
'regex pattern must not be empty')
exit()
# RE pattern validation
try:
search(avoid_re_uid, '')
except sre_constants.error:
print('Invalid avoid_re_uid value, '
'invalid RE pattern: {}'.format(avoid_re_uid))
exit()
if 'prefer_factor' in config_dict:
prefer_factor = string_to_float_convert_test(config_dict['prefer_factor'])
if prefer_factor is None:
print('Invalid prefer_factor value, not float\nExit')
exit()
if prefer_factor < 1 and prefer_factor > 1000:
print('prefer_factor value out of range [1; 1000]\nExit')
exit()
else:
print('prefer_factor not in config\nExit')
exit()
if 'avoid_factor' in config_dict:
avoid_factor = string_to_float_convert_test(config_dict['avoid_factor'])
if avoid_factor is None:
print('Invalid avoid_factor value, not float\nExit')
exit()
if avoid_factor < 1 and avoid_factor > 1000:
print('avoid_factor value out of range [1; 1000]\nExit')
exit()
else:
print('avoid_factor not in config\nExit')
exit()
if 'prefer_cmd_factor' in config_dict:
prefer_cmd_factor = string_to_float_convert_test(
config_dict['prefer_cmd_factor'])
if prefer_cmd_factor is None:
print('Invalid prefer_cmd_factor value, not float\nExit')
exit()
if prefer_cmd_factor < 1 and prefer_cmd_factor > 1000:
print('prefer_cmd_factor value out of range [1; 1000]\nExit')
exit()
else:
print('prefer_cmd_factor not in config\nExit')
exit()
if 'avoid_cmd_factor' in config_dict:
avoid_cmd_factor = string_to_float_convert_test(
config_dict['avoid_cmd_factor'])
if avoid_cmd_factor is None:
print('Invalid avoid_cmd_factor value, not float\nExit')
exit()
if avoid_cmd_factor < 1 and avoid_cmd_factor > 1000:
print('avoid_cmd_factor value out of range [1; 1000]\nExit')
exit()
else:
print('avoid_cmd_factor not in config\nExit')
exit()
if 'prefer_uid_factor' in config_dict:
prefer_uid_factor = string_to_float_convert_test(
config_dict['prefer_uid_factor'])
if prefer_uid_factor is None:
print('Invalid prefer_uid_factor value, not float\nExit')
exit()
if prefer_uid_factor < 1 and prefer_uid_factor > 1000:
print('prefer_uid_factor value out of range [1; 1000]\nExit')
exit()
else:
print('prefer_uid_factor not in config\nExit')
exit()
if 'avoid_uid_factor' in config_dict:
avoid_uid_factor = string_to_float_convert_test(
config_dict['avoid_uid_factor'])
if avoid_uid_factor is None:
print('Invalid avoid_uid_factor value, not float\nExit')
exit()
if avoid_uid_factor < 1 and avoid_uid_factor > 1000:
print('avoid_uid_factor value out of range [1; 1000]\nExit')
exit()
else:
print('avoid_uid_factor not in config\nExit')
exit()
mem_min_sigterm_kb, mem_min_sigterm_mb, mem_min_sigterm_percent = calculate_percent( mem_min_sigterm_kb, mem_min_sigterm_mb, mem_min_sigterm_percent = calculate_percent(
'mem_min_sigterm') 'mem_min_sigterm')
mem_min_sigkill_kb, mem_min_sigkill_mb, mem_min_sigkill_percent = calculate_percent( mem_min_sigkill_kb, mem_min_sigkill_mb, mem_min_sigkill_percent = calculate_percent(

View File

@ -3,6 +3,10 @@
Lines starting with #, tabs and spaces are comments. Lines starting with #, tabs and spaces are comments.
Lines starting with $ contain obligatory parameters.
Lines starting with @ contain optional parameters.
The configuration includes the following sections: The configuration includes the following sections:
1. Memory levels to respond to as an OOM threat 1. Memory levels to respond to as an OOM threat
@ -120,8 +124,6 @@ oom_score_adj_max = 30
##################################################################### #####################################################################
Adjusting the choice of the victim
4. Impact on the badness of processes via matching their names, 4. Impact on the badness of processes via matching their names,
cmdlines or UIDs with regular expressions using re.search(). cmdlines or UIDs with regular expressions using re.search().
@ -144,29 +146,20 @@ oom_score_adj_max = 30
regex_matching = False regex_matching = False
Badness of processes whose names correspond to prefer_regex will Syntax:
be calculated by the following formula:
badness = (oom_score + 1) * prefer_factor
RE patterns must be valid and must not be empty! @PROCESSNAME_RE badness_adj /// RE_pattern
prefer_regex = ^()$ New badness value will be += badness_adj
Valid values are floating-point numbers from the range [1; 1000]. It is possible to compare multiple patterns
with different badness_adj values.
prefer_factor = 2 Example:
Badness of processes whose names correspond to avoid_regex will @PROCESSNAME_RE -100 /// ^Xorg$
be calculated by the following formula: @PROCESSNAME_RE -500 /// ^sshd$
badness = oom_score / avoid_factor @PROCESSNAME_RE 300 /// ^(chromium|firefox)$
# Need more examples
avoid_regex = ^(Xorg|sshd)$
Valid values are floating-point numbers from the range [1; 1000].
avoid_factor = 3
4.2 Matching cmdlines with RE patterns 4.2 Matching cmdlines with RE patterns
@ -175,12 +168,8 @@ avoid_factor = 3
re_match_cmdline = False re_match_cmdline = False
# this default pattern for prefer childs of firefox and chromium @CMDLINE_RE 300 /// -childID|--type=renderer
prefer_re_cmdline = -childID|--type=renderer @CMDLINE_RE -200 /// ^/usr/lib/virtualbox
prefer_cmd_factor = 9
avoid_re_cmdline = ^/usr/lib/virtualbox
avoid_cmd_factor = 3
4.3 Matching UIDs with RE patterns 4.3 Matching UIDs with RE patterns
@ -189,11 +178,7 @@ avoid_cmd_factor = 3
re_match_uid = False re_match_uid = False
prefer_re_uid = ^()$ @UID_RE -100 /// ^0$
prefer_uid_factor = 1
avoid_re_uid = ^(0)$
avoid_uid_factor = 1
Note that you can control badness also via systemd units via OOMScoreAdjust, see Note that you can control badness also via systemd units via OOMScoreAdjust, see
https://www.freedesktop.org/software/systemd/man/systemd.exec.html#OOMScoreAdjust= https://www.freedesktop.org/software/systemd/man/systemd.exec.html#OOMScoreAdjust=