remove trash

This commit is contained in:
Alexey Avramov 2019-07-17 21:41:21 +09:00
parent 7b5cb79c07
commit 9f438726b4
31 changed files with 1 additions and 11824 deletions

View File

@ -31,7 +31,6 @@
- [x] `oom-sort`
- [x] `psi-top`
- [x] `psi-monitor`
- [x] `i-memhog`
- [x] Improve poll rate algorithm
- [x] Fixed Makefile for installation on CentOS 7 (remove gzip `-k` option).
- [x] Added `max_post_sigterm_victim_lifetime` option: send SIGKILL to the victim if it doesn't respond to SIGTERM for a certain time

View File

@ -12,7 +12,6 @@ install:
install -m0755 ./oom-sort $(DESTDIR)/$(PREFIX)/usr/bin/oom-sort
install -m0755 ./psi-top $(DESTDIR)/$(PREFIX)/usr/bin/psi-top
install -m0755 ./psi-monitor $(DESTDIR)/$(PREFIX)/usr/bin/psi-monitor
install -m0755 ./i-memhog $(DESTDIR)/$(PREFIX)/usr/bin/i-memhog
install -d $(DESTDIR)/$(PREFIX)/etc/nohang
-git describe --tags --long --dirty > ./version
@ -41,7 +40,6 @@ uninstall:
rm -fv $(PREFIX)/usr/bin/oom-sort
rm -fv $(PREFIX)/usr/bin/psi-top
rm -fv $(PREFIX)/usr/bin/psi-monitor
rm -fv $(PREFIX)/usr/bin/i-memhog
rm -fv $(PREFIX)/usr/share/man/man1/nohang.1.gz
rm -fv $(PREFIX)/usr/share/man/man1/oom-sort.1.gz
rm -fv $(PREFIX)/lib/systemd/system/nohang.service

View File

@ -292,7 +292,7 @@ See also `man journalctl`.
You can also enable `separate_log` in the config to logging in `/var/log/nohang/nohang.log`.
## Additional tools: oom-sort, psi-top, psi-monitor, i-memhog
## Additional tools: oom-sort, psi-top, psi-monitor
### oom-sort
@ -503,10 +503,6 @@ some 0.29 7.58 14.58 | full 0.28 6.92 13.24
```
</details>
### i-memhog
`i-memhog` is an interactive memory hog for testing purposes.
## Contribution
Use cases, feature requests and any questions are [welcome](https://github.com/hakavlad/nohang/issues).

315
i-memhog
View File

@ -1,315 +0,0 @@
#!/usr/bin/env python3
from signal import signal, SIGTERM
from time import sleep
from sys import exit
import os
# чек общей доступной, для 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 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
def signal_handler(signum, frame):
print('Got signal {}'.format(signum))
# sleep(1)
# exit()
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 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'
)
# бесконечный жор
def inf():
print(
'Вводите целые неотрицательные числа. Чем больше, тем быстрее потребление памяти.\n1000 same обеспечивает потребление на уровне полтора гиг в секунду,\nurandom работает на скорости максимум 170 M/s'
)
same = input("same: ")
urandom = input("urandom: ")
expanding_list = []
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, start побайтовая добивалка!')
terminal()
def selfterm():
os.kill(os.getpid(), signal.SIGTERM)
# жор числп гиг
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():
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
print('WARNING: эта прога способна потратить память и повесить систему, будьте осторожны.')
print('При ее работе следите за показателями памяти.')
print('Ignore SIGTERM? (y|n)')
sss = input(': ')
if sss == 'y':
signal(SIGTERM, signal_handler)
print('The SIGTERM signal will be ignored')
else:
print('The SIGTERM signal will NOT be ignored')
ex_list = []
try:
while True:
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 '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()
print_mem()
selfterm()

View File

@ -1,46 +0,0 @@
Fedora 21 (KDE) Гуглил долго, про oom-killer много чего прочитал. Но не понял, как его активировать. whereis его не нашёл, в репах его не нашёл. Если это встроенное средство - почему у меня не запускается и где его конфиг? Мне нужно тупо, чтобы если оперативка исчерпалась - прибило последнюю вкладку хрома. Либо вообще killall chrome тупо и всё. Как проще всего сделать?
https://www.linux.org.ru/forum/desktop/11511840
OOM Killer под себя
Здравствуйте!
Задача такова, надо (курсовая работа по системному программированию) пропатчить ядро с изменением oom killer'a, т.е.
1)требуется создать некоторый список с названиями процессов, которые "мудрый киллер" будет удалять в первую очередь или наоборот оставлять.
2)требуется создать свою систему расчета приоритетов для удаления процессов.
Я НЕ продвинутый линуксоид, поэтому прошу помощи у общественности. С чего начать и как приступить к выполнению?
https://www.linux.org.ru/forum/development/3555574
Товарищи, можете посоветовать какую-нибудь стандартную программу, которая, в какой-то определённо ситуации, жрала память, что приводило бы к запуску Killer`a.
Чтобы потом можно было на ней тестить курсач)
https://www.linux.org.ru/forum/development/3555574?cid=3570489
Post-mortem по логам OOM-killer.
Суть такова, в определенный момент на машине случилось нечто, в результате чего кончилась физическая память и ОС залезла в своп с головой. Производительность упала до потери всякого отклика от машины. OOM-killer включился, но, похоже, занимался убийством исключительно невиновных и никому не мешающих процессов.
Можно ли как-то по логам отследить, кто сожрал всю память? Хотя бы имена павших жертвами киллера?
Или сразу самому писать скрипт, сбрасывающий на диск ps aux, для следующего такого случая?
https://www.linux.org.ru/forum/admin/5693261
Проблема в том что у меня на VDS мало оперативки и она занята полностью пытаясь подключиться сервер не может выделить памяти и обрывает соединение. что прописать чтобы ссх постоянно висел в процессах с выделенным скажем полумегабайтным или сколько там ему достаточно лимитом?
https://www.linux.org.ru/forum/general/5399920?cid=5399954

View File

@ -1,34 +0,0 @@
#!/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()

View File

@ -1,276 +0,0 @@
# 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)

View File

@ -1,4 +0,0 @@
#!/bin/sh
cp ./memleak /usr/sbin/memleak
cp ./memleak.service /lib/systemd/system/memleak.service
systemctl daemon-reload

View File

@ -1,12 +0,0 @@
#!/usr/bin/env python3
from os import system
from time import sleep
x = []
while True:
x.append('#' * 99999)
sleep(0.1)
system('sleep 9999 &')

View File

@ -1,9 +0,0 @@
[Unit]
Description=Memory leak daemon
After=sysinit.target
[Service]
ExecStart=/usr/sbin/memleak
[Install]
WantedBy=multi-user.target

315
trash/mm
View File

@ -1,315 +0,0 @@
#!/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()

3020
trash/n10

File diff suppressed because it is too large Load Diff

3073
trash/n11

File diff suppressed because it is too large Load Diff

View File

@ -1,140 +0,0 @@
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

File diff suppressed because it is too large Load Diff

View File

@ -1,427 +0,0 @@
This is nohang config file.
Redesign of this config in progress.
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
2. Response on PSI memory metrics
3. The frequency of checking the level of available memory
(and CPU usage)
4. The prevention of killing innocent victims
5. Impact on the badness of processes via matching their
- names,
- cmdlines and
- UIDs
with regular expressions
6. The execution of a specific command instead of sending the
SIGTERM signal
7. GUI notifications:
- OOM prevention results and
- low memory warnings
8. Output verbosity
9. Misc
Just read the description of the parameters and edit the values.
Please restart the program after editing the config.
#####################################################################
1. Thresholds below which a signal should be sent to the victim
Sets the available memory levels at or below which SIGTERM or SIGKILL
signals are sent. The signal will be sent if MemAvailable and
SwapFree (in /proc/meminfo) at the same time will drop below the
corresponding values. Can be specified in % (percent) and M (MiB).
Valid values are floating-point numbers from the range [0; 100] %.
MemAvailable levels.
mem_min_sigterm = 10 %
mem_min_sigkill = 5 %
SwapFree levels.
swap_min_sigterm = 10 %
swap_min_sigkill = 5 %
Specifying the total share of zram in memory, if exceeded the
corresponding signals are sent. As the share of zram in memory
increases, it may fall responsiveness of the system. 90 % is a
usual hang level, not recommended to set very high.
Can be specified in % and M. Valid values are floating-point
numbers from the range [0; 90] %.
zram_max_sigterm = 50 %
zram_max_sigkill = 55 %
#####################################################################
2. Response on PSI memory metrics (it needs Linux 4.20 and up)
About PSI:
https://facebookmicrosites.github.io/psi/
Disabled by default (ignore_psi = True).
ignore_psi = True
Choose a path to PSI file.
By default it monitors system-wide file: /proc/pressure/memory
You also can set file to monitor one cgroup slice.
For example:
psi_path = /sys/fs/cgroup/unified/user.slice/memory.pressure
psi_path = /sys/fs/cgroup/unified/system.slice/memory.pressure
psi_path = /sys/fs/cgroup/unified/system.slice/foo.service/memory.pressure
Execute the command
find /sys/fs/cgroup | grep -P "memory\.pressure$"
to find available memory.pressue files (except /proc/pressure/memory).
psi_path = /proc/pressure/memory
Valid psi_metrics are:
some_avg10
some_avg60
some_avg300
full_avg10
full_avg60
full_avg300
some_avg10 is most sensitive.
psi_metrics = some_avg10
sigterm_psi_threshold = 80
sigkill_psi_threshold = 90
psi_post_action_delay = 60
#####################################################################
3. The frequency of checking the amount of available memory
(and CPU usage)
Coefficients that affect the intensity of monitoring. Reducing
the coefficients can reduce CPU usage and increase the periods
between memory checks.
Why three coefficients instead of one? Because the swap fill rate
is usually lower than the RAM fill rate.
It is possible to set a lower intensity of monitoring for swap
without compromising to prevent OOM and thus reduce the CPU load.
Default values are well for desktop. On servers without rapid
fluctuations in memory levels the values can be reduced.
Valid values are positive floating-point numbers.
rate_mem = 4000
rate_swap = 1500
rate_zram = 500
See also https://github.com/rfjakob/earlyoom/issues/61
Максимальное время сна между проверками памяти.
Положительное число.
max_sleep_time = 3
Минимальное время сна между проверками памяти.
Положительное число, не превышающее max_sleep_time.
min_sleep_time = 0.1
#####################################################################
4. The prevention of killing innocent victims
Минимальное значение bandess (по умолчанию равно oom_score),
которым должен обладать
процесс для того, чтобы ему был отправлен сигнал.
Позволяет предотвратить убийство невиновных если что-то
пойдет не так.
Valid values are integers from the range [0; 1000].
min_badness = 20
Минимальная задержка после отправки соответствующих сигналов
для предотвращения риска убийства сразу множества процессов.
Valid values are non-negative floating-point numbers.
min_delay_after_sigterm = 0.2
min_delay_after_sigkill = 1
Процессы браузера chromium обычно имеют oom_score_adj
200 или 300. Это приводит к тому, что процессы хрома умирают
первыми вместо действительно тяжелых процессов.
Если параметр decrease_oom_score_adj установлен
в значение True, то у процессов, имеющих oom_score_adj выше
oom_score_adj_max значение oom_score_adj будет опущено
до oom_score_adj_max перед поиском жертвы.
Enabling the option requires root privileges.
Valid values are True and False.
Values are case sensitive.
decrease_oom_score_adj = False
Valid values are integers from the range [0; 1000].
oom_score_adj_max = 20
#####################################################################
5. Impact on the badness of processes via matching their names,
cmdlines or UIDs with regular expressions using re.search().
See https://en.wikipedia.org/wiki/Regular_expression and
https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions
Enabling this options slows down the search for the victim
because the names, cmdlines or UIDs of all processes
(except init and kthreads) are compared with the
specified regex patterns (in fact slowing down is caused by
reading all /proc/*/cmdline and /proc/*/status files).
Use script `oom-sort` from nohang package to view
names, cmdlines and UIDs of processes.
5.1 Matching process names with RE patterns
Valid values are True and False.
regex_matching = False
Syntax:
@PROCESSNAME_RE badness_adj /// RE_pattern
New badness value will be += badness_adj
It is possible to compare multiple patterns
with different badness_adj values.
Example:
@PROCESSNAME_RE -100 /// ^Xorg$
@PROCESSNAME_RE -500 /// ^sshd$
5.2 Matching cmdlines with RE patterns
A good option that allows fine adjustment.
re_match_cmdline = False
@CMDLINE_RE 300 /// -childID|--type=renderer
@CMDLINE_RE -200 /// ^/usr/lib/virtualbox
5.3 Matching UIDs with RE patterns
The most slow option
re_match_uid = False
@UID_RE -100 /// ^0$
5.4 Matching CGroup-line with RE patterns
re_match_cgroup = True
@CGROUP_RE -50 /// system.slice
@CGROUP_RE 50 /// foo.service
@CGROUP_RE 2000 /// user.slice
5.5 Matching realpath with RE patterns
re_match_realpath = False
@REALPATH_RE 20 /// ^/usr/bin/foo
Note that you can control badness also via systemd units via OOMScoreAdjust, see
https://www.freedesktop.org/software/systemd/man/systemd.exec.html#OOMScoreAdjust=
#####################################################################
6. The execution of a specific command instead of sending the
SIGTERM signal.
For processes with a specific name you can specify a command to
run instead of sending the SIGTERM signal.
For example, if the process is running as a daemon, you can run
the restart command instead of sending SIGTERM.
Valid values are True and False.
execute_the_command = False
The length of the process name can't exceed 15 characters.
The syntax is as follows: lines starting with keyword $ETC are
considered as the lines containing names of processes and
corresponding commands. After a name of process the triple slash
(///) follows. And then follows the command that will be
executed if the specified process is selected as a victim. The
ampersand (&) at the end of the command will allow nohang to
continue runing without waiting for the end of the command
execution.
For example:
$ETC mysqld /// systemctl restart mariadb.service &
$ETC php-fpm7.0 /// systemctl restart php7.0-fpm.service
If command will contain $PID pattern, this template ($PID) will
be replaced by PID of process which name match with RE pattern.
Exmple:
$ETC bash /// kill -KILL $PID
It is way to send any signal instead of SIGTERM.
(run `kill -L` to see list of all signals)
Also $NAME will be replaced by process name.
$ETC bash /// kill -9 $PID
$ETC firefox-esr /// kill -SEGV $PID
$ETC tail /// kill -9 $PID
$ETC apache2 /// systemctl restart apache2
#####################################################################
7. GUI notifications:
- OOM prevention results and
- low memory warnings
Включение этой опции требует наличия notify-send в системе.
В Debian/Ubuntu это обеспечивается установкой пакета
libnotify-bin. В Fedora и Arch Linux - пакет libnotify.
Также требуется наличие сервера уведомлений.
При запуске nohang от рута уведомления рассылаются всем
залогиненным пользователям.
See also wiki.archlinux.org/index.php/Desktop_notifications
Valid values are True and False.
gui_notifications = False
Enable GUI notifications about the low level of available memory.
Valid values are True and False.
gui_low_memory_warnings = False
Execute the command instead of sending GUI notifications if the value is
not empty line. For example:
warning_exe = cat /proc/meminfo &
warning_exe =
Если значения MemAvailable и SwapFree одновременно будут ниже
соотвестствующих значений, то будут отправлены уведомления.
Can be specified in % (percent) and M (MiB).
Valid values are floating-point numbers from the range [0; 100] %.
mem_min_warnings = 25 %
swap_min_warnings = 25 %
Если доля zram в памяти превысит значение zram_max_warnings,
то будут отправляться уведомления с минимальным периодом равным
min_time_between_warnings.
zram_max_warnings = 40 %
Минимальное время между отправками уведомлений в секундах.
Valid values are floating-point numbers from the range [1; 300].
min_time_between_warnings = 15
Ampersands (&) will be replaced with asterisks (*) in process
names and in commands.
#####################################################################
8. Verbosity
Display the configuration when the program starts.
Valid values are True and False.
print_config = False
Print memory check results.
Valid values are True and False.
print_mem_check_results = False
Минимальная периодичность печати состояния памяти.
0 - печатать все проверки памяти.
Неотрицательное число.
min_mem_report_interval = 60
Print sleep periods between memory checks.
Valid values are True and False.
print_sleep_periods = False
Печатать общую статистику по корректирующим действиям с момента
запуска nohang после каждого корректирующего действия.
print_total_stat = True
Печатать таблицу процессов перед каждым корректирующим действием.
print_proc_table = False
print_victim_info = True
Максимальная глубина показа родословной жертвы.
По умолчанию (1) показывается только родитель - PPID.
Целое положительное число.
max_ancestry_depth = 1
separate_log = False
psi_debug = False
#####################################################################
9. Misc
Жертва может не реагировать на SIGTERM.
max_post_sigterm_victim_lifetime - это время, при превышении
которого жертва получит SIGKILL.
Неотрицательные числа.
max_post_sigterm_victim_lifetime = 10
Execute the command after sending SIGKILL to the victim if the value is
not empty line. For example:
post_kill_exe = cat /proc/meminfo &
post_kill_exe =
forbid_negative_badness = True

View File

@ -1,194 +0,0 @@
#!/usr/bin/env python3
# интерактивный oom-trigger
from memco import *
from signal import signal, SIGTERM
from time import sleep
from sys import exit
def signal_handler(signum, frame):
print('Got signal {}'.format(signum))
# sleep(1)
# exit()
signal(SIGTERM, signal_handler)
# печать показателей на этапах работы
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'
)
# бесконечный жор
def inf():
print(
'Вводите целые неотрицательные числа. Чем больше, тем быстрее потребление памяти.\n1000 same обеспечивает потребление на уровне полтора гиг в секунду,\nurandom работает на скорости максимум 170 M/s'
)
same = input("same: ")
urandom = input("urandom: ")
expanding_list = []
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, 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
print('WARNING: эта прога способна потратить память и повесить систему, будьте осторожны.')
print('При ее работе следите за показателями памяти.')
ex_list = []
try:
while True:
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 '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()
print_mem()
selfterm()

View File

@ -1,98 +0,0 @@
#!/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()

View File

@ -1,82 +0,0 @@
#!/usr/bin/env python3
from ctypes import CDLL
from time import sleep
from sys import argv
"""
Execute the command
find /sys/fs/cgroup -name memory.pressure
to find available memory.pressue files (except /proc/pressure/memory).
(actual for cgroup2)
"""
if len(argv) > 1:
psi_path = argv[1]
else:
psi_path = '/proc/pressure/memory'
def mlockall():
MCL_CURRENT = 1
MCL_FUTURE = 2
MCL_ONFAULT = 4
libc = CDLL('libc.so.6', use_errno=True)
result = libc.mlockall(
MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT
)
if result != 0:
result = libc.mlockall(
MCL_CURRENT | MCL_FUTURE
)
if result != 0:
print('WARNING: cannot lock all memory')
else:
pass
else:
pass
mlockall()
def psi_path_to_metrics(psi_path):
with open(psi_path) as f:
psi_list = f.readlines()
# print(psi_list)
some_list, full_list = psi_list[0].split(' '), psi_list[1].split(' ')
#print(some_list, full_list)
some_avg10 = some_list[1].split('=')[1]
some_avg60 = some_list[2].split('=')[1]
some_avg300 = some_list[3].split('=')[1]
full_avg10 = full_list[1].split('=')[1]
full_avg60 = full_list[2].split('=')[1]
full_avg300 = full_list[3].split('=')[1]
return (some_avg10, some_avg60, some_avg300,
full_avg10, full_avg60, full_avg300)
print('Path to PSI file: {}\n'.format(psi_path))
print(' avg10 avg60 avg300 avg10 avg60 avg300')
while True:
(some_avg10, some_avg60, some_avg300,
full_avg10, full_avg60, full_avg300) = psi_path_to_metrics(psi_path)
print('some {} {} {} | full {} {} {}'.format(
some_avg10.rjust(6),
some_avg60.rjust(6),
some_avg300.rjust(6),
full_avg10.rjust(6),
full_avg60.rjust(6),
full_avg300.rjust(6)))
sleep(2)

View File

@ -1,51 +0,0 @@
#!/usr/bin/env python3
from time import sleep, time
import os
from sys import stdout
mlockall = True
if mlockall:
from ctypes import CDLL
CDLL('libc.so.6').mlockall(3)
psi_path = '/proc/pressure/memory'
psi_support = os.path.exists(psi_path)
def rline1(path):
"""read 1st line from path."""
with open(path) as f:
for line in f:
return line[:-1]
def psi_mem_some_avg_total():
return float(rline1(psi_path).rpartition('=')[2])
avg_min_time = 1
if psi_support:
ta0 = time()
a0 = psi_mem_some_avg_total()
while True:
if psi_support:
ta1= time()
dt = ta1 - ta0
if dt >= avg_min_time:
a1 = psi_mem_some_avg_total()
avg = (a1 - a0) / (ta1 - ta0) / 10000
print('avg time:', round(dt, 1))
print('PSI mem avg:', round(avg, 2))
print(rline1(psi_path), '\n')
ta0 = ta1
a0 = a1
stdout.flush()
sleep(0.1)

View File

@ -1,133 +0,0 @@
#!/usr/bin/env python3
from ctypes import CDLL
from time import sleep, time
import os
"""
Execute the command
find /sys/fs/cgroup -name memory.pressure
to find available memory.pressue files (except /proc/pressure/memory).
(actual for cgroup2)
"""
psi_path = '/proc/pressure/memory'
def mlockall():
MCL_CURRENT = 1
MCL_FUTURE = 2
MCL_ONFAULT = 4
libc = CDLL('libc.so.6', use_errno=True)
result = libc.mlockall(
MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT
)
if result != 0:
result = libc.mlockall(
MCL_CURRENT | MCL_FUTURE
)
if result != 0:
print('WARNING: cannot lock all memory')
else:
pass
else:
pass
mlockall()
t0 = time()
def psi_path_to_metrics(psi_path):
with open(psi_path) as f:
psi_list = f.readlines()
# print(psi_list)
some_list, full_list = psi_list[0].split(' '), psi_list[1].split(' ')
#print(some_list, full_list)
some_avg10 = some_list[1].split('=')[1]
some_avg60 = some_list[2].split('=')[1]
some_avg300 = some_list[3].split('=')[1]
full_avg10 = full_list[1].split('=')[1]
full_avg60 = full_list[2].split('=')[1]
full_avg300 = full_list[3].split('=')[1]
return (some_avg10, some_avg60, some_avg300,
full_avg10, full_avg60, full_avg300)
def cgroup2_root():
"""
"""
with open('/proc/mounts') as f:
for line in f:
if ' cgroup2 ' in line:
# if line.startswith('cgroup2 '):
return line[7:].rpartition(' cgroup2 ')[0]
def get_psi_mem_files(cgroup2_path):
"""
"""
path_list = []
for root, dirs, files in os.walk(cgroup2_path):
for file in files:
path = os.path.join(root, file)
if path.endswith('/memory.pressure'): #############
path_list.append(path)
return path_list
def psi_path_to_cgroup2(path):
"""
"""
return path.partition(i)[2][:-16]
i = cgroup2_root()
print('cgroup2 root dir:', i)
if i is not None:
y = get_psi_mem_files(i)
for path in y:
pass # print(psi_path_to_cgroup2(path))
path_list = get_psi_mem_files(i)
print(' avg10 avg60 avg300 avg10 avg60 avg300 cgroup2')
print(' ----- ----- ------ ----- ----- ------ ---------')
(some_avg10, some_avg60, some_avg300, full_avg10, full_avg60, full_avg300) = psi_path_to_metrics('/proc/pressure/memory')
print('some {} {} {} | full {} {} {} {}'.format(
some_avg10.rjust(6),
some_avg60.rjust(6),
some_avg300.rjust(6),
full_avg10.rjust(6),
full_avg60.rjust(6),
full_avg300.rjust(6), '[SYSTEM]'))
for psi_path in path_list:
(some_avg10, some_avg60, some_avg300,
full_avg10, full_avg60, full_avg300) = psi_path_to_metrics(psi_path)
print('some {} {} {} | full {} {} {} {}'.format(
some_avg10.rjust(6),
some_avg60.rjust(6),
some_avg300.rjust(6),
full_avg10.rjust(6),
full_avg60.rjust(6),
full_avg300.rjust(6), psi_path_to_cgroup2(psi_path)))
print(time() - t0)

View File

@ -1,60 +0,0 @@
#!/usr/bin/env python3
from time import sleep, time
t0 = time()
hog_list = []
duration = 60
sff_max = 0.55
sff_min = 0.45
mb = 1024 * 1024
path = '/dev/zero'
def sff():
"""
SwapFree fraction
"""
with open('/proc/meminfo') as f:
for i in f:
if i.startswith('SwapTotal'):
st = i.split(':')[1].strip(' kB\n')
if i.startswith('SwapFree'):
sf = i.split(':')[1].strip(' kB\n')
st = float(st) + 1
sf = float(sf)
return sf / st
def hog(hog_list):
"""
"""
with open(path, 'rb') as f:
raw = f.read(mb)
hog_list.append(raw)
return hog_list
while True:
while sff() > sff_min:
hog_list.reverse()
if time() - t0 > duration:
exit()
hog_list = hog(hog_list)
print('MiB:', len(hog_list), 'SwapFree:', sff(), 'time:', time() - t0)
while sff() < sff_max:
hog_list.reverse()
if time() - t0 > duration:
exit()
try:
hog_list.pop()
except IndexError:
break
print('MiB:', len(hog_list), 'SwapFree:', sff(), 'time:', time() - t0)

View File

@ -1,2 +0,0 @@
some avg10=56.70 avg60=51.59 avg300=22.92 total=195239452
full avg10=28.82 avg60=49.77 avg300=21.83 total=182504463

View File

@ -1,30 +0,0 @@
#!/usr/bin/env python3
import random
# число элементов в списке, влияет на потребляемую память
n = 400 * 1000 * 1000
# число итераций замены элементов списка
c = 10
print('Наполняем список (n = {}) случайными числами...'.format(n))
try:
# добавляем в пустой список n случайных чисел
x = []
for _ in range(n):
x.append(random.random())
for i in range(c):
print('Читение и запись новых значений, итерация {} из {}'.format(i + 1, c))
# заменяем элементы списка на новые
for i in range(n):
x[i] = x[i] * 0.999
del x
except KeyboardInterrupt:
del x

View File

@ -1,25 +0,0 @@
#!/usr/bin/env python3
# rawcat 1 999 /path/to/file
from sys import argv
print('argv:')
print(argv)
mode = int(argv[1])
num = int(argv[2])
path = argv[3]
if mode == 0:
with open(path, 'rb') as f:
raw = f.read(num)
if mode == 1:
with open(path, 'rb') as f:
raw = f.read(num).decode('utf-8', 'ignore')
if mode == 2:
with open(path) as f:
raw = f.read(num)
print('raw:')
print([raw])

View File

@ -1,17 +0,0 @@
#!/usr/bin/env python3
from signal import signal, SIGTERM
def signal_handler(signum, frame):
print('Got signal {}'.format(signum))
signal(SIGTERM, signal_handler)
rate = 99999
x = []
while True:
x.append('#' * rate)
# http://okturing.com/src/6140/body

View File

@ -1,169 +0,0 @@
#!/usr/bin/env python3
import os
from time import sleep, time
from signal import (signal,
SIGKILL, SIGTERM, SIGINT, SIGQUIT,
SIGCONT, SIGUSR1, SIGUSR2,
SIGHUP, SIGABRT, SIGSEGV, SIGBUS)
from sys import argv, exit
def mlockall():
"""Lock all memory to prevent swapping the process."""
from ctypes import CDLL
MCL_CURRENT = 1
MCL_FUTURE = 2
MCL_ONFAULT = 4
libc = CDLL('libc.so.6', use_errno=True)
result = libc.mlockall(
MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT
)
if result != 0:
result = libc.mlockall(
MCL_CURRENT | MCL_FUTURE
)
if result != 0:
print('WARNING: cannot lock all memory')
else:
log('All memory locked with MCL_CURRENT | MCL_FUTURE')
else:
print('All memory locked with MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT')
def check_mem():
"""find mem_available"""
with open('/proc/meminfo') as f:
for n, line in enumerate(f):
if n is 2:
mem_available = int(line.split(':')[1][:-4])
return mem_available
def pid_to_name(pid):
"""
"""
try:
with open('/proc/' + pid + '/comm', 'rb') as f:
return f.read().decode('utf-8', 'ignore')[:-1]
except FileNotFoundError:
return ''
except ProcessLookupError:
return ''
def pid_to_state(pid):
x = rline1('/proc/' + pid + '/stat')
if ')' in x:
return x.rpartition(')')[2][1]
else:
return ' '
def pid_to_rss(pid):
try:
rss = rline1('/proc/{}/statm'.format(pid)).split(' ')[1]
except IndexError:
rss = '-0'
return rss
def pid_to_realpath(pid):
try:
return os.path.realpath('/proc/' + pid + '/exe')
except FileNotFoundError:
return ''
def rline1(path):
"""read 1st line from path."""
try:
with open(path) as f:
for line in f:
return line[:-1]
except UnicodeDecodeError:
with open(path, 'rb') as f:
return f.read(999).decode(
'utf-8', 'ignore').split('\n')[0] # use partition()!
except FileNotFoundError:
return 'FileNotFoundError'
except ProcessLookupError:
return 'ProcessLookupError'
###############################################################################
if len(argv) != 2:
print("""Usage:
thanatolog PID""")
exit()
mlockall()
pid = argv[1]
name = pid_to_name(pid)
rss0 = float(pid_to_rss(pid))
ma = check_mem()
print('PID:', pid)
print('Name:', name)
print('RSS at startup: {} (100.0 %)'.format(int(rss0)))
print('MemAvail:', ma)
send_signal = SIGKILL
# os.kill(int(pid), SIGCONT)
t0 = time()
for i in range(10):
rpe = os.path.exists('/proc/{}/exe'.format(pid))
rss = pid_to_rss(pid)
pe = os.path.exists('/proc/{}'.format(pid))
t1 = time()
d = t1 - t0
state = pid_to_state(pid)
ma = check_mem()
vv = pid_to_cmdline(pid)
print(vv)
print('RP: {} | RSS: {} ({} %) | State: {} | time: {} | MemAv'
'ail: {}'.format(rpe, rss, round(float(rss) / (
rss0 + 0.0001) * 100, 1), state, round(d, 3), ma))
print('Send SIGKILL')
os.kill(int(pid), send_signal)
t0 = time()
while True:
rpe = os.path.exists('/proc/{}/exe'.format(pid))
rss = pid_to_rss(pid)
pe = os.path.exists('/proc/{}'.format(pid))
t1 = time()
d = t1 - t0
state = pid_to_state(pid)
ma = check_mem()
vv = pid_to_cmdline(pid)
print(vv)
print('RP: {} | RSS: {} ({} %) | State: {} | time: {} | MemAv'
'ail: {}'.format(rpe, rss, round(float(rss) / (
rss0 + 0.0001) * 100, 1), state, round(d, 3), ma))
if pe is False:
print('Process {} ({}) died in {} sec'.format(pid, name, round(d, 3)))
exit()

View File

@ -1,177 +0,0 @@
#!/usr/bin/env python3
import os
from time import sleep, time
from signal import (signal,
SIGKILL, SIGTERM, SIGINT, SIGQUIT,
SIGCONT, SIGUSR1, SIGUSR2,
SIGHUP, SIGABRT, SIGSEGV, SIGBUS)
from sys import argv, exit
def mlockall():
"""Lock all memory to prevent swapping the process."""
from ctypes import CDLL
MCL_CURRENT = 1
MCL_FUTURE = 2
MCL_ONFAULT = 4
libc = CDLL('libc.so.6', use_errno=True)
result = libc.mlockall(
MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT
)
def check_mem():
"""find mem_available"""
with open('/proc/meminfo') as f:
for n, line in enumerate(f):
if n is 2:
mem_available = int(line.split(':')[1][:-4])
return round(mem_available / 1024.0)
def pid_to_name(pid):
"""
"""
try:
with open('/proc/' + pid + '/comm', 'rb') as f:
return f.read().decode('utf-8', 'ignore')[:-1]
except FileNotFoundError:
return ''
except ProcessLookupError:
return ''
def pid_to_state(pid):
x = rline1('/proc/' + pid + '/stat')
if ')' in x:
return x.rpartition(')')[2][1]
else:
return ' '
def pid_to_rss(pid, SC_PAGESIZE):
try:
rss = rline1('/proc/{}/statm'.format(pid)).split(' ')[1]
except IndexError:
rss = '-0'
return round(int(rss) * SC_PAGESIZE / (1024.0 ** 2))
def pid_to_realpath(pid):
try:
return os.path.realpath('/proc/' + pid + '/exe')
except FileNotFoundError:
return ''
def rline1(path):
"""read 1st line from path."""
try:
with open(path) as f:
for line in f:
return line[:-1]
except UnicodeDecodeError:
with open(path, 'rb') as f:
return f.read(999).decode(
'utf-8', 'ignore').split('\n')[0] # use partition()!
except FileNotFoundError:
return 'FileNotFoundError'
except ProcessLookupError:
return 'ProcessLookupError'
###############################################################################
if len(argv) != 2:
print("""Usage:
thanatolog PID""")
exit()
mlockall()
SC_PAGESIZE = os.sysconf(os.sysconf_names['SC_PAGESIZE'])
pid = argv[1]
name = pid_to_name(pid)
rss0 = float(pid_to_rss(pid, SC_PAGESIZE))
ma = check_mem()
print('PID:', pid)
print('Name:', name)
print('RSS at startup: {} (100.0 %)'.format(int(rss0)))
print('MemAvail:', ma)
send_signal = SIGKILL
# os.kill(int(pid), SIGCONT)
t0 = time()
for i in range(10):
sleep(0.001)
rpe = os.path.exists('/proc/{}/exe'.format(pid))
rss = pid_to_rss(pid, SC_PAGESIZE)
pe = os.path.exists('/proc/{}'.format(pid))
t1 = time()
d = t1 - t0
state = pid_to_state(pid)
ma = check_mem()
print('RP: {} | RSS: {} ({} %) | {} | t: {:0<6} | MemAv'
'ail: {}'.format(rpe, rss, round(float(rss) / (
rss0 + 0.0001) * 100, 1), state, str(round(d, 4)), ma))
print()
print('Send SIGKILL')
os.kill(int(pid), send_signal)
t0 = time()
ma0 = ma
while True:
sleep(0.001)
rpe = os.path.exists('/proc/{}/exe'.format(pid))
rss = pid_to_rss(pid, SC_PAGESIZE)
pe = os.path.exists('/proc/{}'.format(pid))
t1 = time()
d = t1 - t0
state = pid_to_state(pid)
ma = check_mem()
print('RP: {} | RSS: {} ({} %) | State: {} | time: {} | MemAvail: {} | dMA {}'.format(
rpe, rss, round(float(rss) / (rss0 + 0.0001) * 100, 1), state, round(d, 3), ma, ma0 - ma))
if pe is False:
break
print('Process {} ({}) died in {} sec'.format(pid, name, round(d, 3)))
print()
for i in range(10):
sleep(0.001)
rpe = os.path.exists('/proc/{}/exe'.format(pid))
rss = pid_to_rss(pid, SC_PAGESIZE)
pe = os.path.exists('/proc/{}'.format(pid))
t1 = time()
d = t1 - t0
state = pid_to_state(pid)
ma = check_mem()
print('RP: {} | RSS: {} ({} %) | State: {} | time: {} | MemAvail: {} | dMA {}'.format(
rpe, rss, round(float(rss) / (rss0 + 0.0001) * 100, 1), state, round(d, 3), ma, ma0 - ma))

124
trash/x01
View File

@ -1,124 +0,0 @@
#!/usr/bin/env python3
from os import getpid
# find mem_total
# find positions of SwapFree and SwapTotal in /proc/meminfo
with open('/proc/meminfo') as f:
mem_list = f.readlines()
mem_list_names = []
for s in mem_list:
mem_list_names.append(s.split(':')[0])
if mem_list_names[2] != 'MemAvailable':
errprint('WARNING: Your Linux kernel is too old, Linux 3.14+ requied')
# exit(1)
swap_total_index = mem_list_names.index('SwapTotal')
swap_free_index = swap_total_index + 1
mem_total = int(mem_list[0].split(':')[1][:-4])
# 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])
ppid_index = status_names.index('PPid')
vm_size_index = status_names.index('VmSize')
vm_rss_index = status_names.index('VmRSS')
vm_swap_index = status_names.index('VmSwap')
uid_index = status_names.index('Uid')
state_index = status_names.index('State')
try:
anon_index = status_names.index('RssAnon')
file_index = status_names.index('RssFile')
shmem_index = status_names.index('RssShmem')
detailed_rss = True
# print(detailed_rss, 'detailed_rss')
except ValueError:
detailed_rss = False
# print('It is not Linux 4.5+')
self_pid = str(getpid())
def self_rss():
r = pid_to_status(self_pid)[5]
print(r)
def pid_to_status(pid):
"""
"""
try:
with open('/proc/' + pid + '/status') as f:
for n, line in enumerate(f):
if n is 0:
name = line.split('\t')[1][:-1]
if n is state_index:
state = line.split('\t')[1][0]
continue
if n is ppid_index:
ppid = line.split('\t')[1][:-1]
continue
if n is uid_index:
uid = line.split('\t')[2]
continue
if n is vm_size_index:
vm_size = int(line.split('\t')[1][:-4])
continue
if n is vm_rss_index:
vm_rss = int(line.split('\t')[1][:-4])
continue
if n is vm_swap_index:
vm_swap = int(line.split('\t')[1][:-4])
break
return name, state, ppid, uid, vm_size, vm_rss, vm_swap
except UnicodeDecodeError:
return pid_to_status_unicode(pid)
except FileNotFoundError:
return None
except ProcessLookupError:
return None
except ValueError:
return None
self_rss()
import logging
import subprocess
import argparse
self_rss()

View File

@ -1,10 +0,0 @@
#!/bin/sh
# Deactivate swap
swapoff /dev/zram0
# Reset zram
echo 1 > /sys/block/zram0/reset
# Remove zram module
modprobe -r zram

View File

@ -1,27 +0,0 @@
#!/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