upd misc
This commit is contained in:
parent
b08787de58
commit
16e749b03f
34
misc/isascii
Executable file
34
misc/isascii
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Check file for non-ascii lines."""
|
||||
|
||||
from sys import argv
|
||||
|
||||
path = argv[1]
|
||||
|
||||
print('Path:', path)
|
||||
|
||||
|
||||
def isascii(string):
|
||||
try:
|
||||
string_ascii = string.encode('ascii')
|
||||
return True
|
||||
except UnicodeEncodeError:
|
||||
return False
|
||||
|
||||
|
||||
def check_file():
|
||||
num = 0
|
||||
with open(path) as f:
|
||||
for n, line in enumerate(f):
|
||||
res = isascii(line)
|
||||
if res:
|
||||
continue
|
||||
else:
|
||||
print('Line {} is non-ascii:'.format(n + 1))
|
||||
print(line.strip('\n'))
|
||||
num += 1
|
||||
continue
|
||||
print('Found {} non-ascii lines'.format(num))
|
||||
|
||||
|
||||
check_file()
|
276
misc/memco.py
Normal file
276
misc/memco.py
Normal file
@ -0,0 +1,276 @@
|
||||
# memdler common
|
||||
|
||||
import os
|
||||
import glob
|
||||
import signal
|
||||
import subprocess
|
||||
from glob import glob
|
||||
from time import sleep
|
||||
|
||||
|
||||
# k = mem_total_used / (zram own size)
|
||||
k = 0.0042
|
||||
|
||||
|
||||
def meminfo():
|
||||
|
||||
# получаем сырой mem_list
|
||||
with open('/proc/meminfo') as file:
|
||||
mem_list = file.readlines()
|
||||
|
||||
# получаем список названий позиций: MemTotal etc
|
||||
mem_list_names = []
|
||||
for s in mem_list:
|
||||
mem_list_names.append(s.split(':')[0])
|
||||
|
||||
# ищем MemAvailable, обрабатываем исключение
|
||||
try:
|
||||
mem_available_index = mem_list_names.index('MemAvailable')
|
||||
except ValueError:
|
||||
print("Your Linux kernel is too old (3.14+ requied), bye!")
|
||||
# исключение для ядер < 3.14, не определяющих MemAvailable
|
||||
exit()
|
||||
|
||||
# ищем позиции SwapTotl и SwapFree
|
||||
swap_total_index = mem_list_names.index('SwapTotal')
|
||||
swap_free_index = mem_list_names.index('SwapFree')
|
||||
|
||||
buffers_index = mem_list_names.index('Buffers')
|
||||
cached_index = mem_list_names.index('Cached')
|
||||
active_index = mem_list_names.index('Active')
|
||||
inactive_index = mem_list_names.index('Inactive')
|
||||
shmem_index = mem_list_names.index('Shmem')
|
||||
|
||||
# ищем значение MemTotal в KiB
|
||||
mem_total = int(mem_list[0].split(':')[1].split(' ')[-2])
|
||||
|
||||
return mem_total, mem_available_index, swap_total_index, swap_free_index, buffers_index, cached_index, active_index, inactive_index, shmem_index
|
||||
|
||||
|
||||
meminfo_tuple = meminfo()
|
||||
|
||||
mem_total = meminfo_tuple[0]
|
||||
mem_available_index = meminfo_tuple[1]
|
||||
swap_total_index = meminfo_tuple[2]
|
||||
swap_free_index = meminfo_tuple[3]
|
||||
|
||||
buffers_index = meminfo_tuple[4]
|
||||
cached_index = meminfo_tuple[5]
|
||||
active_index = meminfo_tuple[6]
|
||||
inactive_index = meminfo_tuple[7]
|
||||
shmem_index = meminfo_tuple[8]
|
||||
|
||||
|
||||
def meminfo_num(mem_list, index):
|
||||
return int(mem_list[index].split(':')[1].split(' ')[-2])
|
||||
|
||||
|
||||
# выдача основных показателей meminfo, KiB
|
||||
def mem_check_main():
|
||||
|
||||
with open('/proc/meminfo') as file:
|
||||
mem_list = file.readlines()
|
||||
|
||||
mem_available = meminfo_num(mem_list, mem_available_index)
|
||||
swap_total = meminfo_num(mem_list, swap_total_index)
|
||||
swap_free = meminfo_num(mem_list, swap_free_index)
|
||||
|
||||
return mem_available, swap_total, swap_free
|
||||
|
||||
|
||||
# читать не весь файл, а нужный срез от 0 до 20, например
|
||||
def mem_check_full():
|
||||
|
||||
with open('/proc/meminfo') as file:
|
||||
mem_list = file.readlines()
|
||||
|
||||
mem_available = meminfo_num(mem_list, mem_available_index)
|
||||
swap_total = meminfo_num(mem_list, swap_total_index)
|
||||
swap_free = meminfo_num(mem_list, swap_free_index)
|
||||
|
||||
buffers = meminfo_num(mem_list, buffers_index)
|
||||
cached = meminfo_num(mem_list, cached_index)
|
||||
active = meminfo_num(mem_list, active_index)
|
||||
inactive = meminfo_num(mem_list, inactive_index)
|
||||
shmem = meminfo_num(mem_list, shmem_index)
|
||||
|
||||
return mem_available, swap_total, swap_free, buffers, cached, active, inactive, shmem
|
||||
|
||||
|
||||
# чек общей доступной, для lim2avail
|
||||
def total_mem_available():
|
||||
|
||||
with open('/proc/meminfo') as file:
|
||||
mem_list = file.readlines()
|
||||
|
||||
mem_available = meminfo_num(mem_list, mem_available_index)
|
||||
swap_free = meminfo_num(mem_list, swap_free_index)
|
||||
|
||||
return round((swap_free + mem_available) / 1024) # MiB
|
||||
|
||||
|
||||
# добитие байтами рандома
|
||||
def terminal():
|
||||
ex = []
|
||||
while True:
|
||||
try:
|
||||
ex.append(os.urandom(1))
|
||||
except MemoryError:
|
||||
continue
|
||||
|
||||
|
||||
# перевод дроби в проценты
|
||||
def percent(num):
|
||||
a = str(round(num * 100, 1)).split('.')
|
||||
a0 = a[0].rjust(3, ' ')
|
||||
a1 = a[1]
|
||||
return '{}.{}'.format(a0, a1)
|
||||
|
||||
|
||||
def human(num):
|
||||
return str(round(num / 1024.0)).rjust(8, ' ')
|
||||
|
||||
|
||||
|
||||
# B -> GiB
|
||||
def humanz(num):
|
||||
a = str(round(num / 1073741824, 3))
|
||||
a0 = a.split('.')[0].rjust(4, ' ')
|
||||
a1 = a.split('.')[1]
|
||||
if len(a1) == 1:
|
||||
a1 += '00'
|
||||
if len(a1) == 2:
|
||||
a1 += '0'
|
||||
return '{}.{}'.format(a0, a1)
|
||||
|
||||
|
||||
|
||||
movie_dict = {
|
||||
'+----': '-+---',
|
||||
'-+---': '--+--',
|
||||
'--+--': '---+-',
|
||||
'---+-': '----+',
|
||||
'----+': '+----'
|
||||
}
|
||||
|
||||
|
||||
def config_parser(config):
|
||||
if os.path.exists(config):
|
||||
try:
|
||||
with open(config) as f:
|
||||
name_value_dict = dict()
|
||||
for line in f:
|
||||
a = line.startswith('#')
|
||||
b = line.startswith('\n')
|
||||
c = line.startswith('\t')
|
||||
d = line.startswith(' ')
|
||||
if not a and not b and not c and not d:
|
||||
a = line.split('=')
|
||||
name_value_dict[a[0].strip()] = a[1].strip()
|
||||
return name_value_dict
|
||||
except PermissionError:
|
||||
print('config: permission error')
|
||||
else:
|
||||
print('config does not exists')
|
||||
|
||||
|
||||
|
||||
|
||||
def swaps_raw(part_string):
|
||||
'''анализ строки свопс, возврат кортежа с значениями'''
|
||||
part_string_list = part_string.split('\t')
|
||||
part_name = part_string_list[0].split(' ')[0]
|
||||
|
||||
part_size = int(part_string_list[-3])
|
||||
part_used = int(part_string_list[-2])
|
||||
part_prio = int(part_string_list[-1])
|
||||
|
||||
return part_name, part_size, part_used, part_prio
|
||||
|
||||
|
||||
|
||||
# возвращает disksize и mem_used_total по zram id
|
||||
def zram_stat(zram_id):
|
||||
with open('/sys/block/zram' + zram_id + '/disksize') as file:
|
||||
disksize = file.readlines()[0][:-1]
|
||||
if os.path.exists('/sys/block/zram' + zram_id + '/mm_stat'):
|
||||
with open('/sys/block/zram' + zram_id + '/mm_stat') as file:
|
||||
mm_stat = file.readlines()[0][:-1].split(' ')
|
||||
mm_stat_list = []
|
||||
for i in mm_stat:
|
||||
if i != '':
|
||||
mm_stat_list.append(i)
|
||||
mem_used_total = mm_stat_list[2]
|
||||
else:
|
||||
with open('/sys/block/zram' + zram_id + '/mem_used_total') as file:
|
||||
mem_used_total = file.readlines()[0][:-1]
|
||||
return disksize, mem_used_total
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# termer(signal.SIGKILL)
|
||||
# process terminator
|
||||
# функция поиска жиробаса и его убийства
|
||||
def terminator(signal):
|
||||
|
||||
subdirs = glob('/proc/*/')
|
||||
subdirs.remove('/proc/self/')
|
||||
subdirs.remove('/proc/thread-self/')
|
||||
|
||||
pid_list = []
|
||||
name_list = []
|
||||
oom_score_list = []
|
||||
|
||||
for subdir in subdirs:
|
||||
|
||||
try:
|
||||
|
||||
with open(subdir + 'status') as file:
|
||||
status = file.readlines()
|
||||
|
||||
pid_list.append(status[5].split(':')[1][1:-1])
|
||||
name_list.append(status[0].split(':')[1][1:-1])
|
||||
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
try:
|
||||
|
||||
with open(subdir + 'oom_score') as file:
|
||||
oom_score = file.readlines()
|
||||
|
||||
oom_score_list.append(int(oom_score[0][0:-1]))
|
||||
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
max_oom_score = sorted(oom_score_list)[-1]
|
||||
n = oom_score_list.index(max_oom_score)
|
||||
s = sorted(oom_score_list)
|
||||
s.reverse()
|
||||
|
||||
if signal == signal.SIGTERM:
|
||||
print('\nTRY TO TERM {}, Pid {}\n'.format(name_list[n], pid_list[n]))
|
||||
else:
|
||||
print('\nTRY TO KILL {}, Pid {}\n'.format(name_list[n], pid_list[n]))
|
||||
|
||||
try:
|
||||
os.kill(int(pid_list[n]), signal)
|
||||
except ProcessLookupError:
|
||||
print('No such process')
|
||||
|
||||
|
||||
|
||||
|
||||
def selfterm():
|
||||
os.kill(os.getpid(), signal.SIGTERM)
|
||||
|
||||
|
||||
|
||||
|
||||
|
315
misc/mm
Executable file
315
misc/mm
Executable file
@ -0,0 +1,315 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ms-monitor/
|
||||
|
||||
from memco import *
|
||||
import time
|
||||
|
||||
# once or 1, log or 2, inplace or 3
|
||||
mode = '3'
|
||||
|
||||
# период цикла печати
|
||||
period = 0.2
|
||||
|
||||
# параметры визуализации
|
||||
used = '$'
|
||||
free = '~'
|
||||
len_visual = 14
|
||||
|
||||
# нахождение и печать параметров, возвращает показатели и принимает показатели для нахождения дельт
|
||||
def printer(old_list):
|
||||
|
||||
mem_tup = mem_check_main()
|
||||
|
||||
mem_available = mem_tup[0]
|
||||
swap_total = mem_tup[1]
|
||||
swap_free = mem_tup[2]
|
||||
|
||||
tn = time.time()
|
||||
delta = tn - old_list[4]
|
||||
|
||||
mem_busy = mem_total - mem_available
|
||||
swap_busy = swap_total - swap_free
|
||||
|
||||
mem_swap_total = mem_total + swap_total
|
||||
mem_swap_free = mem_available + swap_free
|
||||
mem_swap_busy = mem_busy + swap_busy
|
||||
|
||||
delta_mem = (mem_busy - old_list[0]) / delta
|
||||
delta_swap = (swap_busy - old_list[1]) / delta
|
||||
delta_all = (mem_swap_busy - old_list[2]) / delta
|
||||
|
||||
if swap_total == 0:
|
||||
|
||||
#1###################################################################################
|
||||
|
||||
# печать без свопа
|
||||
|
||||
mem_visual = (
|
||||
used * round(mem_busy / mem_total * len_visual)
|
||||
).ljust(len_visual, free)
|
||||
|
||||
print(
|
||||
' MEM'
|
||||
)
|
||||
|
||||
print(
|
||||
'TOTAL {}'.format(
|
||||
human(mem_total),
|
||||
)
|
||||
)
|
||||
print(
|
||||
'N/A {} {}'.format(
|
||||
human(mem_busy),
|
||||
percent(mem_busy / mem_total),
|
||||
)
|
||||
)
|
||||
print(
|
||||
'AVAIL {} {}'.format(
|
||||
human(mem_available),
|
||||
percent(mem_available / mem_total),
|
||||
)
|
||||
)
|
||||
print(
|
||||
'DELTA {}'.format(
|
||||
human(delta_mem),
|
||||
)
|
||||
)
|
||||
print(
|
||||
'{} {}'.format(
|
||||
old_list[3], mem_visual
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
#2###################################################################################
|
||||
|
||||
else:
|
||||
|
||||
with open('/proc/swaps') as file:
|
||||
swaps_list = file.readlines()[1:]
|
||||
|
||||
zram_id_list = []
|
||||
|
||||
disk_swap_size = 0
|
||||
disk_swap_used = 0
|
||||
zram_swap_size = 0
|
||||
zram_swap_used = 0
|
||||
|
||||
for i in swaps_list:
|
||||
|
||||
x = swaps_raw(i)
|
||||
|
||||
if x[0].startswith('/dev/zram'):
|
||||
|
||||
zram_swap_size += int(x[1])
|
||||
zram_swap_used += int(x[2])
|
||||
|
||||
zram_id_list.append(x[0][9:])
|
||||
|
||||
else:
|
||||
|
||||
disk_swap_size += int(x[1])
|
||||
disk_swap_used += int(x[2])
|
||||
|
||||
if zram_swap_size == 0:
|
||||
|
||||
#3###################################################################################
|
||||
|
||||
# печать своп без зрам
|
||||
|
||||
mem_visual = (
|
||||
used * round(mem_busy / mem_total * len_visual)
|
||||
).ljust(len_visual, free)
|
||||
swap_visual = (
|
||||
used * round(swap_busy / swap_total * len_visual)
|
||||
).ljust(len_visual, free)
|
||||
mem_swap_visual = (
|
||||
used * round(mem_swap_busy / mem_swap_total * len_visual)
|
||||
).ljust(len_visual, free)
|
||||
|
||||
print(
|
||||
' MEM SWAP MEM + SWAP'
|
||||
)
|
||||
|
||||
print(
|
||||
'TOTAL {} {} {}'.format(
|
||||
human(mem_total),
|
||||
human(swap_total),
|
||||
human(mem_swap_total),
|
||||
)
|
||||
)
|
||||
print(
|
||||
'N/A {} {} {} {} {} {}'.format(
|
||||
human(mem_busy),
|
||||
percent(mem_busy / mem_total),
|
||||
human(swap_busy),
|
||||
percent(swap_busy / swap_total),
|
||||
human(mem_swap_busy),
|
||||
percent(mem_swap_busy / mem_swap_total),
|
||||
)
|
||||
)
|
||||
print(
|
||||
'AVAIL {} {} {} {} {} {}'.format(
|
||||
human(mem_available),
|
||||
percent(mem_available / mem_total),
|
||||
human(swap_free),
|
||||
percent(swap_free / swap_total),
|
||||
human(mem_swap_free),
|
||||
percent(mem_swap_free / mem_swap_total),
|
||||
)
|
||||
)
|
||||
print(
|
||||
'DELTA {} {} {}'.format(
|
||||
human(delta_mem),
|
||||
human(delta_swap),
|
||||
human(delta_all)
|
||||
)
|
||||
)
|
||||
print(
|
||||
'{} {} {} {}'.format(
|
||||
old_list[3],
|
||||
mem_visual,
|
||||
swap_visual,
|
||||
mem_swap_visual,
|
||||
)
|
||||
)
|
||||
print()
|
||||
|
||||
#4###################################################################################
|
||||
|
||||
else:
|
||||
|
||||
# суммируем показатели из всех свопов в зрам
|
||||
|
||||
disksize_sum = 0
|
||||
mem_used_total_sum = 0
|
||||
|
||||
for i in zram_id_list:
|
||||
s = zram_stat(i) # кортеж из disksize и mem_used_total для данного zram id
|
||||
disksize_sum += int(s[0])
|
||||
mem_used_total_sum += int(s[1])
|
||||
|
||||
# находим показатели для ZRAM
|
||||
full = disksize_sum * k + mem_used_total_sum
|
||||
profit = zram_swap_used - (full / 1024)
|
||||
cr_real = round(zram_swap_used * 1024 / mem_used_total_sum, 2)
|
||||
|
||||
#5###################################################################################
|
||||
|
||||
# печать своп + зрам
|
||||
|
||||
mem_visual = (
|
||||
used * round(mem_busy / mem_total * len_visual)
|
||||
).ljust(len_visual, free)
|
||||
swap_visual = (
|
||||
used * round(swap_busy / swap_total * len_visual)
|
||||
).ljust(len_visual, free)
|
||||
mem_swap_visual = (
|
||||
used * round(mem_swap_busy / mem_swap_total * len_visual)
|
||||
).ljust(len_visual, free)
|
||||
zram_visual = (
|
||||
used * round(full / 1024 / mem_total * 18)
|
||||
).ljust(18, free)
|
||||
|
||||
print(
|
||||
' MEM SWAP MEM + SWAP ZRAM SWAP'
|
||||
)
|
||||
|
||||
print(
|
||||
'TOTAL {} {} {} PROFIT {} M'.format(
|
||||
human(mem_total),
|
||||
human(swap_total),
|
||||
human(mem_swap_total),
|
||||
human(profit)
|
||||
)
|
||||
)
|
||||
print(
|
||||
'N/A {} {} {} {} {} {} CR {}'.format(
|
||||
human(mem_busy),
|
||||
percent(mem_busy / mem_total),
|
||||
human(swap_busy),
|
||||
percent(swap_busy / swap_total),
|
||||
human(mem_swap_busy),
|
||||
percent(mem_swap_busy / mem_swap_total),
|
||||
str(cr_real).rjust(7, ' ')
|
||||
)
|
||||
)
|
||||
print(
|
||||
'AVAIL {} {} {} {} {} {} FULL/MT {} %'.format(
|
||||
human(mem_available),
|
||||
percent(mem_available / mem_total),
|
||||
human(swap_free),
|
||||
percent(swap_free / swap_total),
|
||||
human(mem_swap_free),
|
||||
percent(mem_swap_free / mem_swap_total),
|
||||
percent(full / 1024 / mem_total)
|
||||
)
|
||||
)
|
||||
print(
|
||||
'DELTA {} {} {}'.format(
|
||||
human(delta_mem),
|
||||
human(delta_swap),
|
||||
human(delta_all)
|
||||
)
|
||||
)
|
||||
print(
|
||||
'{} {} {} {} {}'.format(
|
||||
old_list[3],
|
||||
mem_visual,
|
||||
swap_visual,
|
||||
mem_swap_visual,
|
||||
zram_visual
|
||||
)
|
||||
)
|
||||
print()
|
||||
|
||||
#6###################################################################################
|
||||
|
||||
# печать по партициям
|
||||
|
||||
print('FILENAME USED SIZE PRIORITY')
|
||||
|
||||
for i in swaps_list:
|
||||
x = swaps_raw(i)
|
||||
print(
|
||||
'{} {} G {} % {} G {}'.format(
|
||||
str(x[0]).ljust(26, ' '),
|
||||
human(x[2]),
|
||||
percent(x[2] / x[1]), human(x[1]),
|
||||
str(x[3]).rjust(10, ' ')
|
||||
)
|
||||
)
|
||||
|
||||
return [mem_busy, swap_busy, mem_swap_busy, movie_dict[(old_list[3])], tn]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
try:
|
||||
|
||||
delta = [0, 0, 0, '+----', 0]
|
||||
|
||||
if mode == 'log' or mode == '2':
|
||||
|
||||
while True:
|
||||
delta = printer(delta)
|
||||
sleep(period)
|
||||
|
||||
elif mode == 'inplace' or mode == '3':
|
||||
|
||||
while True:
|
||||
print("\033c")
|
||||
delta = printer(delta)
|
||||
sleep(period)
|
||||
|
||||
else:
|
||||
|
||||
delta = printer(delta)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
exit()
|
||||
|
140
misc/new5.conf
Normal file
140
misc/new5.conf
Normal file
@ -0,0 +1,140 @@
|
||||
This is nohang config file.
|
||||
Lines starting with $ contain obligatory parameters.
|
||||
Lines starting with @ contain optional parameters.
|
||||
Other lines are comments.
|
||||
|
||||
0. Common zram settings
|
||||
|
||||
See https://www.kernel.org/doc/Documentation/blockdev/zram.txt
|
||||
You maybe need $IGNORE_ZRAM=FALSE if you has a big zram disksize
|
||||
|
||||
$IGNORE_ZRAM = TRUE
|
||||
|
||||
1. Common PSI settings
|
||||
|
||||
See
|
||||
https://lwn.net/Articles/759658/
|
||||
https://facebookmicrosites.github.io/psi/
|
||||
|
||||
$IGNORE_PSI = TRUE
|
||||
|
||||
$PSI_PATH = /proc/pressure/memory
|
||||
|
||||
some_avg10 is most sensitive.
|
||||
|
||||
$PSI_METRICS = some_avg10
|
||||
|
||||
$PSI_EXCESS_DURATION = 0
|
||||
|
||||
$PSI_POST_ACTION_DELAY = 40
|
||||
|
||||
|
||||
|
||||
2. Poll rate
|
||||
|
||||
$FILL_RATE_MEM = 4000
|
||||
$FILL_RATE_SWAP = 1500
|
||||
$FILL_RATE_ZRAM = 500
|
||||
$MIN_SLEEP = 0.1
|
||||
$MAX_SLEEP = 3
|
||||
|
||||
|
||||
3. Warnings / GUI notifications
|
||||
|
||||
$GUI_CORRECTIVE_ACTIONS = FALSE
|
||||
|
||||
$GUI_LOW_MEMORY_WARNINGS = FALSE
|
||||
$GUI_WARNINGS_MIN_MEM = 20 %
|
||||
$GUI_WARNINGS_MIN_SWAP = 20 %
|
||||
$GUI_WARNINGS_MAX_ZRAM = 45 %
|
||||
$GUI_MIN_DELAY_AFTER_WARNING = 15
|
||||
|
||||
@EXE_INSTEAD_OF_GUI_WARNING wall -n "LOW MEMORY!"
|
||||
@EXE_INSTEAD_OF_GUI_WARNING echo 'test'
|
||||
|
||||
|
||||
4. Soft threshold / SIGTERM-related parameters
|
||||
|
||||
$SOFT_MIN_MEM_THRESHOLD = 10 %
|
||||
$SOFT_MIN_SWAP_THRESHOLD = 10 %
|
||||
$SOFT_MAX_ZRAM_THRESHOLD = 50 %
|
||||
|
||||
$SOFT_POST_ACTION_DELAY = 0.2
|
||||
|
||||
$MAX_POST_SOFT_ACTION_VICTIM_LIFETIME = 9
|
||||
|
||||
$SOFT_MAX_PSI_THRESHOLD = 60
|
||||
$SOFT_MAX_PSI_DURATION = 5
|
||||
|
||||
The execution of specified command instead of sending the SIGTERM signal.
|
||||
Syntax example:
|
||||
<key> <regular expression> /// <command>
|
||||
|
||||
@EXE_INSTEAD_OF_SIGTERM_RE_NAME ^foo$ /// kill -9 $PID && echo "Praise KEK, kill $NAME" &
|
||||
|
||||
@EXE_INSTEAD_OF_SIGTERM_RE_CMDLINE ^/sbin/foo /// systemctl restart foo
|
||||
|
||||
@EXE_INSTEAD_OF_SIGTERM_RE_REALPATH ^/sbin/bar$ /// systemctl restart foo
|
||||
|
||||
@EXE_INSTEAD_OF_SIGTERM_RE_UID ^1000$ /// pkill -SEGV $NAME
|
||||
@EXE_INSTEAD_OF_SIGTERM_RE_UID ^1001$ /// pkill -HUP $NAME
|
||||
|
||||
@SOFT_THRESHOLD_EXE_RE_NAME
|
||||
|
||||
5. Hard threshold / SIGKILL-related parameters
|
||||
|
||||
$HARD_MIN_MEM_THRESHOLD = 5 %
|
||||
$HARD_MIN_SWAP_THRESHOLD = 5 %
|
||||
$HARD_MAX_ZRAM_THRESHOLD = 55 %
|
||||
|
||||
$POST_KILL_EXE =
|
||||
|
||||
$HARD_POST_ACTION_DELAY = 1
|
||||
|
||||
$HARD_MAX_PSI_THRESHOLD = 90
|
||||
$HARD_MAX_PSI_DURATION = 5
|
||||
|
||||
|
||||
$POST_KILL_EXE =
|
||||
|
||||
|
||||
|
||||
6. Adjusting badness of processes
|
||||
|
||||
$OOM_SCORE_ADJ_LIMIT = -1
|
||||
|
||||
Badness adjusting by matching process name, cmdline and eUID with specified regular expression.
|
||||
|
||||
Example badness adj rules
|
||||
<key> <regular expression> /// <badness_adj>
|
||||
|
||||
@BADNESS_ADJ_RE_CMDLINE -childID|--type=renderer /// 200
|
||||
|
||||
@BADNESS_ADJ_RE_NAME ^Xorg$ /// -100
|
||||
|
||||
@BADNESS_ADJ_RE_UID ^0$ /// -50
|
||||
|
||||
@BADNESS_ADJ_RE_REALPATH ^/usr/bin/tail$ /// 100
|
||||
|
||||
|
||||
|
||||
7. Avoid killing small processes (innocent victims)
|
||||
|
||||
$MIN_VICTIM_BADNESS = 20
|
||||
|
||||
|
||||
8. Verbosity
|
||||
|
||||
$PRINT_CONFIG_AT_STARTUP = FALSE // --print-config
|
||||
|
||||
$MIN_MEM_REPORT_INTERVAL = -1
|
||||
|
||||
$PRINT_VICTIM_INFO = TRUE
|
||||
|
||||
$PRINT_TOTAL_STAT = TRUE
|
||||
|
||||
$PRINT_PROC_TABLE = FALSE
|
||||
|
||||
$PRINT_SLEEP_PERIODS = FALSE
|
||||
|
||||
|
@ -1,102 +0,0 @@
|
||||
|
||||
This is nohang config file.
|
||||
Lines starting with $ contain obligatory parameters.
|
||||
Lines starting with @ contain optional parameters.
|
||||
Other lines are comments.
|
||||
|
||||
|
||||
1. Ignore PSI and zram.
|
||||
|
||||
$IGNORE_PSI = TRUE
|
||||
$IGNORE_ZRAM = TRUE
|
||||
|
||||
|
||||
2. Poll rate
|
||||
|
||||
$POLL_RATE = 60
|
||||
$MIN_SLEEP = 0.1
|
||||
$MAX_SLEEP = 2
|
||||
|
||||
|
||||
3. GUI notifications
|
||||
|
||||
$GUI_CORRECTIVE_ACTIONS = FALSE
|
||||
|
||||
$GUI_LOW_MEMORY_WARNINGS = FALSE
|
||||
$GUI_WARNINGS_MIN_MEM = 20 %
|
||||
$GUI_WARNINGS_MIN_SWAP = 20 %
|
||||
$GUI_WARNINGS_MAX_ZRAM = 45 %
|
||||
$GUI_MIN_DELAY_AFTER_WARNING = 15
|
||||
|
||||
@EXE_INSTEAD_OF_GUI_WARNING wall -n "LOW MEMORY!"
|
||||
@EXE_INSTEAD_OF_GUI_WARNING echo 'test'
|
||||
@EXE_INSTEAD_OF_GUI_WARNING echo 'test2'
|
||||
|
||||
|
||||
4. SIGTERM-related parameters
|
||||
|
||||
$SIGTERM_MIN_MEM = 10 %
|
||||
$SIGTERM_MIN_SWAP = 10 %
|
||||
$SIGTERM_MAX_ZRAM = 50 %
|
||||
$DELAY_AFTER_SIGTERM = 0.2
|
||||
|
||||
$SIGTERM_MAX_PSI_SOME_AVG10_THRESHOLD = 60
|
||||
$SIGTERM_MAX_PSI_SOME_AVG10_DURATION = 5
|
||||
$DELAY_AFTER_SIGTERM_PSI_SOME_AVG10 = 40
|
||||
|
||||
The execution of specified command instead of sending a SIGTERM signal.
|
||||
Syntax example:
|
||||
<key> <regular expression> /// <command>
|
||||
|
||||
@EXE_INSTEAD_OF_SIGTERM_RE_PROCESSNAME ^foo$ /// kill -9 $PID && echo "Praise KEK, kill $NAME" &
|
||||
|
||||
@EXE_INSTEAD_OF_SIGTERM_RE_CMDLINE ^/sbin/foo /// systemctl restart foo
|
||||
|
||||
@EXE_INSTEAD_OF_SIGTERM_RE_UID ^1000$ /// pkill -SEGV $NAME
|
||||
@EXE_INSTEAD_OF_SIGTERM_RE_UID ^1001$ /// pkill -HUP $NAME
|
||||
|
||||
|
||||
5. SIGKILL-related parameters
|
||||
|
||||
$SIGKILL_MIN_MEM = 5 %
|
||||
$SIGKILL_MIN_SWAP = 5 %
|
||||
$SIGKILL_MAX_ZRAM = 55 %
|
||||
$DELAY_AFTER_SIGKILL = 1
|
||||
|
||||
$SIGKILL_MAX_PSI_SOME_AVG10_THRESHOLD = 90
|
||||
$SIGKILL_MAX_PSI_SOME_AVG10_DURATION = 5
|
||||
$DELAY_AFTER_SIGKILL_PSI_SOME_AVG10 = 60
|
||||
|
||||
|
||||
6. Adjusting badness of processes
|
||||
|
||||
$OOM_SCORE_ADJ_LIMIT = -1
|
||||
|
||||
|
||||
Badness adjusting by matching process name, cmdline and eUID with specified regular expression.
|
||||
Example badness adj rules
|
||||
<key> <regular expression> /// <badness_adj>
|
||||
|
||||
@BADNESS_ADJ_RE_CMDLINE -childID|--type=renderer /// 200
|
||||
|
||||
@BADNESS_ADJ_RE_NAME ^Xorg$ /// -100
|
||||
|
||||
@BADNESS_ADJ_RE_UID ^0$ /// -50
|
||||
|
||||
|
||||
7. Avoid killing small processes (innocent victims)
|
||||
|
||||
$MIN_VICTIM_BADNESS = 20
|
||||
|
||||
|
||||
8. Verbosity
|
||||
|
||||
$PRINT_CONFIG_AT_STARTUP = FALSE
|
||||
|
||||
$PRINT_TOTAL_STAT = TRUE
|
||||
|
||||
$PRINT_MEM_CHECK_RESULTS = FALSE
|
||||
$MIN_DELAY_AFTER_PRINT_MEM_CHECK_RESULTS = 60
|
||||
|
||||
$PRINT_SLEEP_PERIODS = FALSE
|
||||
|
223
misc/oom-trigger
223
misc/oom-trigger
@ -1,125 +1,180 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Interactive OOM trigger
|
||||
"""
|
||||
|
||||
import os
|
||||
from argparse import ArgumentParser
|
||||
# интерактивный oom-trigger
|
||||
|
||||
|
||||
##########################################################################
|
||||
from memco import *
|
||||
|
||||
# печать показателей на этапах работы
|
||||
def print_mem():
|
||||
|
||||
mem_tup = mem_check_main()
|
||||
|
||||
mem_available = mem_tup[0]
|
||||
swap_total = mem_tup[1]
|
||||
swap_free = mem_tup[2]
|
||||
|
||||
print(
|
||||
'MemAvailable: ', round(mem_available / 1024 / 1024, 3), 'GiB,', round(mem_available / 1024), 'MiB,', round(mem_available / mem_total * 100, 1), '%'
|
||||
)
|
||||
|
||||
if swap_total != 0:
|
||||
print(
|
||||
'SwapFree: ', round(swap_free / 1024 / 1024, 3), 'GiB,', round(swap_free / 1024), 'MiB,', round(swap_free / swap_total * 100, 1), '%'
|
||||
)
|
||||
print(
|
||||
'Total Free: ', round((mem_available + swap_free) / 1024 / 1024, 3), 'GiB,', round((mem_available + swap_free) / 1024), 'MiB,', round((mem_available + swap_free) / (mem_total + swap_total) * 100, 1), '%'
|
||||
)
|
||||
else:
|
||||
print(
|
||||
'Swap disabled'
|
||||
)
|
||||
|
||||
|
||||
# find mem_total
|
||||
# find positions of SwapFree and SwapTotal in /proc/meminfo
|
||||
|
||||
with open('/proc/meminfo') as file:
|
||||
mem_list = file.readlines()
|
||||
|
||||
mem_list_names = []
|
||||
for s in mem_list:
|
||||
mem_list_names.append(s.split(':')[0])
|
||||
|
||||
if mem_list_names[2] != 'MemAvailable':
|
||||
print('Your Linux kernel is too old, Linux 3.14+ requied\nExit')
|
||||
exit()
|
||||
|
||||
swap_total_index = mem_list_names.index('SwapTotal')
|
||||
swap_free_index = swap_total_index + 1
|
||||
|
||||
mem_total = int(mem_list[0].split(':')[1].strip(' kB\n'))
|
||||
|
||||
# Get names from /proc/*/status to be able to get VmRSS and VmSwap values
|
||||
|
||||
with open('/proc/self/status') as file:
|
||||
status_list = file.readlines()
|
||||
|
||||
status_names = []
|
||||
for s in status_list:
|
||||
status_names.append(s.split(':')[0])
|
||||
|
||||
vm_rss_index = status_names.index('VmRSS')
|
||||
vm_swap_index = status_names.index('VmSwap')
|
||||
|
||||
|
||||
# вариант - сжирать мегабайты исходя из собственного VmRSS + VmSwap
|
||||
|
||||
|
||||
print(mem_total, swap_total_index, swap_free_index, vm_rss_index, vm_swap_index)
|
||||
|
||||
|
||||
##########################################################################
|
||||
|
||||
|
||||
def continue_anyway():
|
||||
"""
|
||||
Mem hog if mem err
|
||||
"""
|
||||
expanding_list = []
|
||||
while True:
|
||||
try:
|
||||
expanding_list.append(os.urandom(1))
|
||||
except MemoryError:
|
||||
continue
|
||||
|
||||
|
||||
def unlimited_memhog():
|
||||
'''
|
||||
unlimited mem hogging
|
||||
'''
|
||||
print('Вводите целые неотрицательные числа. Чем больше, тем быстрее потребление памяти.\n1000 same обеспечивает потребление на уровне полтора гиг в секунду,\nurandom работает на скорости максимум 170 M/s')
|
||||
# бесконечный жор
|
||||
def inf():
|
||||
|
||||
print(
|
||||
'Вводите целые неотрицательные числа. Чем больше, тем быстрее потребление памяти.\n1000 same обеспечивает потребление на уровне полтора гиг в секунду,\nurandom работает на скорости максимум 170 M/s'
|
||||
)
|
||||
same = input("same: ")
|
||||
urandom = input("urandom: ")
|
||||
|
||||
expanding_list = []
|
||||
|
||||
print('Unlimited memhogging started!')
|
||||
print(
|
||||
'Процесс неограниченного потребления пошёл... Press Ctrl + C for exit'
|
||||
)
|
||||
|
||||
while True:
|
||||
try:
|
||||
expanding_list.append(os.urandom(int(urandom)))
|
||||
expanding_list.append('#' * int(same))
|
||||
except MemoryError:
|
||||
print('MemoryError; continue anyway!')
|
||||
continue_anyway()
|
||||
print('MemoryError, start побайтовая добивалка!')
|
||||
terminal()
|
||||
|
||||
|
||||
|
||||
|
||||
# жор числп гиг
|
||||
def lim():
|
||||
|
||||
expanding_list = []
|
||||
|
||||
n = input('На сколько гигабайт уменьшить доступную память?\n: ')
|
||||
|
||||
print('Погнали тратить ' + n + ' гиг...')
|
||||
|
||||
i = 0
|
||||
|
||||
while True:
|
||||
|
||||
i += 1
|
||||
|
||||
try:
|
||||
expanding_list.append(os.urandom(int(100)))
|
||||
expanding_list.append('#' * int(300))
|
||||
except MemoryError:
|
||||
print('MemoryError!')
|
||||
break
|
||||
if i > 2020202 * int(n):
|
||||
print('DONE')
|
||||
break
|
||||
|
||||
return expanding_list
|
||||
|
||||
|
||||
|
||||
|
||||
# жор до остатка мегабайт
|
||||
def lim2avail():
|
||||
|
||||
expanding_list = []
|
||||
|
||||
n = input(
|
||||
'Сколько мегабайт общей доступной памяти (MemAvailable + SwapFree) оставить?\nВведите целое положительное число: '
|
||||
)
|
||||
|
||||
# проверка на целое положительное
|
||||
if n.isdigit() == True:
|
||||
n = int(n)
|
||||
else:
|
||||
print(
|
||||
'Вы ввели не целое положительное число'
|
||||
)
|
||||
return 0
|
||||
|
||||
if n == 0:
|
||||
print(
|
||||
'Вы ввели не целое положительное число'
|
||||
)
|
||||
return 0
|
||||
|
||||
print(
|
||||
'Погнали уменьшать доступную память до уровня ниже ' + str(n) + ' MiB...'
|
||||
)
|
||||
|
||||
while True:
|
||||
try:
|
||||
expanding_list.append(os.urandom(5000))
|
||||
expanding_list.append('#' * 5000)
|
||||
except MemoryError:
|
||||
print('MemoryError!')
|
||||
break
|
||||
if total_mem_available() <= n:
|
||||
print('DONE')
|
||||
break
|
||||
|
||||
return expanding_list
|
||||
|
||||
|
||||
|
||||
##########################################################################
|
||||
|
||||
|
||||
# basic bifurcation
|
||||
|
||||
print('WARNING: эта прога способна потратить память и повесить систему, будьте осторожны.')
|
||||
print('При ее работе следите за показателями памяти.')
|
||||
|
||||
|
||||
expanding_list = []
|
||||
|
||||
|
||||
'''
|
||||
hogging не то
|
||||
u - unlimited mem hogging with choice of speed and entropy
|
||||
n - limited mem hogging (hog указанный далее объем метров)
|
||||
a - уменьшать обем общей доступной памяти (MemAvailable + SwapFree) до тех пор, пока он не станет ниже заданного далее объема
|
||||
|
||||
'''
|
||||
|
||||
ex_list = []
|
||||
|
||||
try:
|
||||
while True:
|
||||
|
||||
print('Select an option from the list below, enter selected letter and press Enter')
|
||||
print()
|
||||
print_mem()
|
||||
print()
|
||||
print('Выберите вариант из списка ниже')
|
||||
print('8 или i или I - запустить бесконечное потребление, предложив выбрать скорость потребления и энтропию')
|
||||
print('7 или l или L - запустить ограниченное потребление заданного числа гигов')
|
||||
print('6 или a или A - жрать память пока количество доступной памяти не опустится ниже заданного')
|
||||
print('0 или с или С - очистить накопления при их наличии')
|
||||
print('q или любой другой символ - выход (можно просто нажать Enter)')
|
||||
|
||||
li = input(': ')
|
||||
|
||||
if li is 'i' or li is 'I' or li is '8':
|
||||
unlimited_memhog()
|
||||
if li is 'l' or li is 'L' or li is '7':
|
||||
x = lim()
|
||||
ex_list.append(x)
|
||||
elif li is 'i' or li is 'I' or li is '8':
|
||||
inf()
|
||||
elif li is 'c' or li is 'C' or li is '0':
|
||||
ex_list = []
|
||||
x = 0
|
||||
y = 0
|
||||
elif li is '6' or li is 'a' or li is 'A':
|
||||
y = lim2avail()
|
||||
ex_list.append(y)
|
||||
else:
|
||||
exit()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print()
|
||||
os.kill(os.getpid(), 15)
|
||||
print_mem()
|
||||
selfterm()
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
98
misc/proc2log
Executable file
98
misc/proc2log
Executable file
@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# proc2log: new processes monitor
|
||||
|
||||
import os
|
||||
import argparse
|
||||
from time import sleep
|
||||
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument(
|
||||
'-p',
|
||||
'--period',
|
||||
help='peroid in seconds between proc checks, default value: 0.1',
|
||||
default=0.1,
|
||||
type=float
|
||||
)
|
||||
args = parser.parse_args()
|
||||
period = args.period
|
||||
|
||||
unknown_name = '<unknown>'
|
||||
|
||||
|
||||
# получение чистого пид сета
|
||||
def foo():
|
||||
proc_list = os.listdir('/proc')
|
||||
proc_set = set()
|
||||
for i in proc_list:
|
||||
if i.isdigit() != True:
|
||||
continue
|
||||
proc_set.add(i)
|
||||
return proc_set
|
||||
|
||||
|
||||
# имя через пид
|
||||
def pid_to_name(pid):
|
||||
try:
|
||||
with open('/proc/' + pid + '/status') as f:
|
||||
for line in f:
|
||||
return line[:-1].split('\t')[1]
|
||||
except FileNotFoundError:
|
||||
return unknown_name
|
||||
|
||||
|
||||
# печать одного пида и имени
|
||||
def print_pid(pid):
|
||||
|
||||
try:
|
||||
with open('/proc/' + pid + '/status') as f:
|
||||
for lineno, line in enumerate(f):
|
||||
name = line[:-1].split('\t')[1]
|
||||
print('+ {}, {}'.format(pid, name))
|
||||
pid_dict[pid] = name
|
||||
if lineno >= 0:
|
||||
break
|
||||
|
||||
except FileNotFoundError:
|
||||
name = pid_dict.pop(pid, unknown_name)
|
||||
print(' - {}, {}'.format(pid, name))
|
||||
|
||||
except ProcessLookupError:
|
||||
name = pid_dict.pop(pid, unknown_name)
|
||||
print(' - {}, {}'.format(pid, name))
|
||||
|
||||
|
||||
# нахождение и печать дельт сетов
|
||||
def delta(old_set):
|
||||
|
||||
new_set = set(os.listdir('/proc'))
|
||||
plus = new_set - old_set
|
||||
minus = old_set - new_set
|
||||
|
||||
if len(plus) > 0:
|
||||
for pid in plus:
|
||||
print_pid(pid)
|
||||
|
||||
if len(minus) > 0:
|
||||
for pid in minus:
|
||||
print_pid(pid)
|
||||
|
||||
return new_set
|
||||
|
||||
|
||||
print('proc2log started with period {} seconds'.format(period))
|
||||
print('+ PID, NAME - PID, NAME')
|
||||
|
||||
# первичное наполнение словаря значениями pid:name для печати имён исчезнувших процессов
|
||||
pid_dict = dict()
|
||||
for pid in foo():
|
||||
pid_dict[pid] = pid_to_name(pid)
|
||||
|
||||
pid_set = set(os.listdir('/proc'))
|
||||
try:
|
||||
while True:
|
||||
pid_set = delta(pid_set)
|
||||
sleep(period)
|
||||
except KeyboardInterrupt:
|
||||
exit()
|
||||
|
10
misc/zram-off
Executable file
10
misc/zram-off
Executable file
@ -0,0 +1,10 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Deactivate swap
|
||||
swapoff /dev/zram0
|
||||
|
||||
# Reset zram
|
||||
echo 1 > /sys/block/zram0/reset
|
||||
|
||||
# Remove zram module
|
||||
modprobe -r zram
|
27
misc/zram-on
Executable file
27
misc/zram-on
Executable file
@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
# загружаем в ядро модуль zram
|
||||
modprobe -v zram num_devices=4
|
||||
|
||||
# задаем число потоков сжатия, равное числу ядер процессора
|
||||
CPUS="`nproc`"
|
||||
echo "$CPUS" > /sys/block/zram0/max_comp_streams
|
||||
|
||||
# выбираем алгоритм сжатия, lz4 наиболее быстр, lzo сильнее сжимает
|
||||
ALG=lzo
|
||||
echo "$ALG" > /sys/block/zram0/comp_algorithm
|
||||
|
||||
# задаем размер zram (FRACTION - размер устройства zram0 в процентах от MemTotal)
|
||||
FRACTION=100
|
||||
MEMORY=`perl -ne'/^MemTotal:\s+(\d+)/ && print $1*1024;' < /proc/meminfo`
|
||||
SIZE=$(( MEMORY * FRACTION / 100 ))
|
||||
|
||||
echo $SIZE > /sys/block/zram0/disksize
|
||||
#echo 10G > /sys/block/zram0/disksize # можно задать размер zram в гигабайтах, вместо процентов от MemTotal
|
||||
|
||||
# форматируем устройство zram0 как swap
|
||||
mkswap -L zram0 /dev/zram0
|
||||
|
||||
# включаем подкачку
|
||||
swapon -d -p 10 /dev/zram0
|
||||
|
Loading…
Reference in New Issue
Block a user