From 16e749b03f0e3f1960fa9b4de23780853f81fa90 Mon Sep 17 00:00:00 2001 From: Alexey Avramov Date: Thu, 21 Mar 2019 23:34:55 +0900 Subject: [PATCH] upd misc --- misc/isascii | 34 +++++ misc/memco.py | 276 +++++++++++++++++++++++++++++++++++++ misc/mm | 315 +++++++++++++++++++++++++++++++++++++++++++ misc/new5.conf | 140 +++++++++++++++++++ misc/nohang_new.conf | 102 -------------- misc/oom-trigger | 223 ++++++++++++++++++------------ misc/proc2log | 98 ++++++++++++++ misc/zram-off | 10 ++ misc/zram-on | 27 ++++ 9 files changed, 1039 insertions(+), 186 deletions(-) create mode 100755 misc/isascii create mode 100644 misc/memco.py create mode 100755 misc/mm create mode 100644 misc/new5.conf delete mode 100644 misc/nohang_new.conf create mode 100755 misc/proc2log create mode 100755 misc/zram-off create mode 100755 misc/zram-on diff --git a/misc/isascii b/misc/isascii new file mode 100755 index 0000000..a897776 --- /dev/null +++ b/misc/isascii @@ -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() diff --git a/misc/memco.py b/misc/memco.py new file mode 100644 index 0000000..c17a6b5 --- /dev/null +++ b/misc/memco.py @@ -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) + + + + + diff --git a/misc/mm b/misc/mm new file mode 100755 index 0000000..792e953 --- /dev/null +++ b/misc/mm @@ -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() + diff --git a/misc/new5.conf b/misc/new5.conf new file mode 100644 index 0000000..46681bd --- /dev/null +++ b/misc/new5.conf @@ -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: + /// + +@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 + /// + +@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 + + diff --git a/misc/nohang_new.conf b/misc/nohang_new.conf deleted file mode 100644 index 41685ba..0000000 --- a/misc/nohang_new.conf +++ /dev/null @@ -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: - /// - -@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 - /// - -@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 - diff --git a/misc/oom-trigger b/misc/oom-trigger index b9b7592..2f2959e 100755 --- a/misc/oom-trigger +++ b/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() + + + + + diff --git a/misc/proc2log b/misc/proc2log new file mode 100755 index 0000000..14127f5 --- /dev/null +++ b/misc/proc2log @@ -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 = '' + + +# получение чистого пид сета +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() + diff --git a/misc/zram-off b/misc/zram-off new file mode 100755 index 0000000..f8aea9b --- /dev/null +++ b/misc/zram-off @@ -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 diff --git a/misc/zram-on b/misc/zram-on new file mode 100755 index 0000000..7507b2f --- /dev/null +++ b/misc/zram-on @@ -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 +