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():
"""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 = []
@ -346,45 +349,30 @@ def fattest():
if regex_matching:
name = pid_to_name(pid)
for re_tup in processname_re_list:
if search(re_tup[1], name) is not None:
if pid_to_cmdline(pid) == '':
# skip kthreads
continue
badness += int(re_tup[0])
if search(avoid_regex, name) is not None:
if pid_to_cmdline(pid) == '':
# skip kthreads
continue
badness = int(badness / avoid_factor)
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:
cmdline = pid_to_cmdline(pid)
if cmdline == '':
# skip kthreads
continue
if search(avoid_re_cmdline, cmdline) is not None:
badness = int(badness / avoid_cmd_factor)
if search(prefer_re_cmdline, cmdline) is not None:
badness = int((badness + 1) * prefer_cmd_factor)
for re_tup in cmdline_re_list:
if search(re_tup[1], cmdline) is not None:
badness += int(re_tup[0])
if re_match_uid:
uid = pid_to_uid(pid)
if search(avoid_re_uid, uid) is not None:
if pid_to_cmdline(pid) == '':
# skip kthreads
continue
badness = int(badness / avoid_uid_factor)
if search(prefer_re_uid, uid) is not None:
if pid_to_cmdline(pid) == '':
# skip kthreads
continue
badness = int((badness + 1) * prefer_uid_factor)
for re_tup in uid_re_list:
if search(re_tup[1], uid) is not None:
if pid_to_cmdline(pid) == '':
# skip kthreads
continue
badness += int(re_tup[0])
except FileNotFoundError:
continue
@ -760,8 +748,14 @@ try:
# dictionary with config options
config_dict = dict()
processname_re_list = []
cmdline_re_list = []
uid_re_list = []
# dictionary with names and commands for the parameter
# execute_the_command
# тут тоже список нужен, а не словарь
etc_dict = dict()
for line in f:
@ -787,6 +781,21 @@ try:
exit()
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:
print('PermissionError', conf_err_mess)
exit()
@ -800,6 +809,9 @@ except IndexError:
print('IndexError', conf_err_mess)
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')
if regex_matching or re_match_cmdline or re_match_uid:
from re import search
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')
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 $ contain obligatory parameters.
Lines starting with @ contain optional parameters.
The configuration includes the following sections:
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,
cmdlines or UIDs with regular expressions using re.search().
@ -144,29 +146,20 @@ oom_score_adj_max = 30
regex_matching = False
Badness of processes whose names correspond to prefer_regex will
be calculated by the following formula:
badness = (oom_score + 1) * prefer_factor
Syntax:
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
be calculated by the following formula:
badness = oom_score / avoid_factor
# Need more examples
avoid_regex = ^(Xorg|sshd)$
Valid values are floating-point numbers from the range [1; 1000].
avoid_factor = 3
@PROCESSNAME_RE -100 /// ^Xorg$
@PROCESSNAME_RE -500 /// ^sshd$
@PROCESSNAME_RE 300 /// ^(chromium|firefox)$
4.2 Matching cmdlines with RE patterns
@ -175,12 +168,8 @@ avoid_factor = 3
re_match_cmdline = False
# this default pattern for prefer childs of firefox and chromium
prefer_re_cmdline = -childID|--type=renderer
prefer_cmd_factor = 9
avoid_re_cmdline = ^/usr/lib/virtualbox
avoid_cmd_factor = 3
@CMDLINE_RE 300 /// -childID|--type=renderer
@CMDLINE_RE -200 /// ^/usr/lib/virtualbox
4.3 Matching UIDs with RE patterns
@ -189,11 +178,7 @@ avoid_cmd_factor = 3
re_match_uid = False
prefer_re_uid = ^()$
prefer_uid_factor = 1
avoid_re_uid = ^(0)$
avoid_uid_factor = 1
@UID_RE -100 /// ^0$
Note that you can control badness also via systemd units via OOMScoreAdjust, see
https://www.freedesktop.org/software/systemd/man/systemd.exec.html#OOMScoreAdjust=