diff --git a/Makefile b/Makefile index 519e3cf..d69b747 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,10 @@ -# +VERSION ?= $(shell git describe --tags --long --dirty > /etc/nohang/version 2> /dev/null) PREFIX = / all: @ echo "Nothing to compile. Use: make install, make uninstall, make systemd" -install: +install: install -d $(DESTDIR)/$(PREFIX)/usr/sbin install -m0755 ./nohang $(DESTDIR)/$(PREFIX)/usr/sbin/nohang install -m0755 ./nohang_notify_helper $(DESTDIR)/$(PREFIX)/usr/sbin/nohang_notify_helper @@ -14,8 +14,8 @@ install: install -m0755 ./oom-trigger $(DESTDIR)/$(PREFIX)/usr/bin/oom-trigger install -d $(DESTDIR)/$(PREFIX)/etc/nohang - install -m0644 ./nohang.conf $(DESTDIR)/$(PREFIX)/etc/nohang - install -m0644 ./nohang.conf $(DESTDIR)/$(PREFIX)/etc/nohang/nohang.conf.backup + install -m0644 ./nohang.conf $(DESTDIR)/$(PREFIX)/etc/nohang/$(VERSION) + install -m0644 ./nohang.conf $(DESTDIR)/$(PREFIX)/etc/nohang/nohang.conf.default install -d $(DESTDIR)/$(PREFIX)/usr/share/man/man1 gzip -k -c nohang.1 > $(DESTDIR)/$(PREFIX)/usr/share/man/man1/nohang.1.gz diff --git a/nohang b/nohang index 29b2758..181b6ce 100755 --- a/nohang +++ b/nohang @@ -7,6 +7,7 @@ from time import sleep, time from operator import itemgetter from sys import stdout, stderr, argv, exit from signal import SIGKILL, SIGTERM +import sys start_time = time() @@ -50,11 +51,10 @@ HR = '' victim_dict = dict() +# extra_process_table_info = None -extra_process_table_info = None - - - +# will store corrective actions stat +stat_dict = dict() ########################################################################## @@ -62,6 +62,87 @@ extra_process_table_info = None # define functions + +def print_version(): + try: + v = rline1('/etc/nohang/version') + except FileNotFoundError: + v = None + if v is None: + print('nohang unknown version') + else: + print(v) + exit() + + + + + + + + +def test(): + + print(sys.version) + print(sys.argv) + + hr = '==================================' + print(hr) + print("uptime()") + print(uptime()) + + print(hr) + print("pid_to_starttime('self')") + print(pid_to_starttime('self')) + + print(hr) + print("get_victim_id('self')") + print(get_victim_id('self')) + + print(hr) + print("errprint('test')") + print(errprint('test')) + + print(hr) + print("mlockall()") + print(mlockall()) + + print(hr) + print("pid_to_state('2')") + print(pid_to_state('2')) + + + ''' + print(hr) + print("update_stat_dict_and_print('key')") + print(update_stat_dict_and_print('key')) + + print(hr) + print("psi_mem_some_avg_total()") + print(psi_mem_some_avg_total()) + + print(hr) + print("psi_mem_some_avg10()") + print(psi_mem_some_avg10()) + + print(hr) + print("check_mem()") + print(check_mem()) + + print(hr) + print("os.uname()") + print(os.uname()) + + print(hr) + print("check_mem()") + print(check_mem()) + + ''' + + print(hr) + exit() + + def uptime(): return float(rline1('/proc/uptime').split(' ')[0]) @@ -146,11 +227,13 @@ def psi_mem_some_avg_total(): def psi_mem_some_avg10(): - return float(rline1(psi_path).split(' ')[1].split('=')[1]) + if psi_support: + return float(rline1(psi_path).split(' ')[1].split('=')[1]) def check_mem(): """find mem_available""" + # исправить название фции return int(rline1('/proc/meminfo').split(':')[1][:-4]) @@ -402,7 +485,6 @@ def pid_to_cmdline(pid): return f.read().replace('\x00', ' ').rstrip() - def pid_to_realpath(pid): try: return os.path.realpath('/proc/' + pid + '/exe') @@ -410,10 +492,6 @@ def pid_to_realpath(pid): return '' - - - - def pid_to_uid(pid): '''return euid''' try: @@ -508,6 +586,8 @@ def send_notify_warn(): round(swap_free / (swap_total + 0.1) * 100) ) + b = 'head ' + str(b.encode()) + t0 = time() os.system(b) t1 = time() @@ -682,7 +762,7 @@ def find_victim(): pid_to_uid(pid).rjust(10), pid_to_cmdline(pid) # pid_to_realpath(pid) - ) + ) ) pid_badness_list.append((pid, badness)) @@ -718,7 +798,6 @@ def find_victim(): def find_victim_info(pid, victim_badness, name): - status0 = time() try: @@ -964,7 +1043,9 @@ def implement_corrective_action(signal): etc_info = '\nImplement a corrective action:\n Run the command: {}' \ '\n Exit status: {}; total response time: {} ms'.format( - command.replace('$PID', pid).replace('$NAME', pid_to_name(pid)), + command.replace( + '$PID', pid).replace( + '$NAME', pid_to_name(pid)), exit_status, round(response_time * 1000)) @@ -1042,7 +1123,6 @@ def implement_corrective_action(signal): key = 'victim badness < min_badness' update_stat_dict_and_print(key) - print('###############################################################################') sleep_after_send_signal(signal) @@ -1167,6 +1247,11 @@ def calculate_percent(arg_key): ########################################################################## + + + + + if len(argv) == 1: if os.path.exists('./nohang.conf'): config = cd = os.getcwd() + '/nohang.conf' @@ -1175,8 +1260,12 @@ if len(argv) == 1: elif len(argv) == 2: if argv[1] == '--help' or argv[1] == '-h': - errprint(help_mess) - exit(1) + print(help_mess) + exit() + elif argv[1] == '--version' or argv[1] == '-v': + print_version() + elif argv[1] == '--test' or argv[1] == '-t': + test() else: errprint('Invalid CLI input') exit(1) @@ -1193,6 +1282,14 @@ else: exit(1) + + + + + + + + ########################################################################## @@ -1267,8 +1364,7 @@ uid_re_list = [] # тут тоже список нужен, а не словарь etc_dict = dict() -# will store corrective actions stat -stat_dict = dict() + try: with open(config) as f: @@ -1340,14 +1436,7 @@ except FileNotFoundError: # validation of all parameters - print_victim_info = conf_parse_bool('print_victim_info') - - - - - - print_config = conf_parse_bool('print_config') print_mem_check_results = conf_parse_bool('print_mem_check_results') print_sleep_periods = conf_parse_bool('print_sleep_periods') @@ -1355,16 +1444,12 @@ gui_low_memory_warnings = conf_parse_bool('gui_low_memory_warnings') gui_notifications = conf_parse_bool('gui_notifications') decrease_oom_score_adj = conf_parse_bool('decrease_oom_score_adj') execute_the_command = conf_parse_bool('execute_the_command') - - ignore_psi = conf_parse_bool('ignore_psi') - regex_matching = conf_parse_bool('regex_matching') - re_match_cmdline = conf_parse_bool('re_match_cmdline') - re_match_uid = conf_parse_bool('re_match_uid') + if regex_matching or re_match_cmdline or re_match_uid: from re import search import sre_constants @@ -1648,6 +1733,30 @@ if max_sleep_time < min_sleep_time: ########################################################################## + + + + + + + + + + + + + + + + + + + + + + + + # Get KiB levels if it's possible. # получ кб. если не кб - то процент. Если процент - находим кб ниже на @@ -1851,6 +1960,9 @@ if print_mem_check_results: report0 = 0 + + + while True: if psi_support and not ignore_psi: @@ -1944,7 +2056,8 @@ while True: just_percent_mem(mem_available / mem_total), human(swap_free, swap_len), just_percent_swap(swap_free / (swap_total + 0.1)), - speed_info) + speed_info + ) ) else: diff --git a/nohang_notify_helper b/nohang_notify_helper index 06e9d95..df8c8b5 100755 --- a/nohang_notify_helper +++ b/nohang_notify_helper @@ -4,14 +4,14 @@ # ./nohang_notify_helper "title" "body" from sys import argv, stdout -from os import listdir +from os import listdir, path from subprocess import Popen, TimeoutExpired if len(argv) < 2 or argv[1] == "-h" or argv[1] == "--help": print('Usage: ./nohang_notify_helper "title" "body"') exit(1) -wait_time = 10 +wait_time = 15 display_env = 'DISPLAY=' dbus_env = 'DBUS_SESSION_BUS_ADDRESS=' @@ -57,21 +57,19 @@ def re_pid_environ(pid): if i.startswith('HOME=/var'): return None - try: - # dirty hack; todo: fix alg env = user.partition('USER=')[2], display, dbus except UnboundLocalError: - print('notify helper: UnboundLocalError') + # print('notify helper: UnboundLocalError') return None return env except FileNotFoundError: - print('notify helper: FileNotFoundError') + # print('notify helper: FileNotFoundError') return None except ProcessLookupError: - print('notify helper: ProcessLookupError') + # print('notify helper: ProcessLookupError') return None @@ -80,10 +78,11 @@ def root_notify_env(): unsorted_envs_list = [] # iterates over processes, find processes with suitable env for pid in listdir('/proc'): - if pid[0].isdecimal() is False: - continue - one_env = re_pid_environ(pid) - unsorted_envs_list.append(one_env) + + if path.exists('/proc/' + pid + '/exe') is True: + one_env = re_pid_environ(pid) + unsorted_envs_list.append(one_env) + env = set(unsorted_envs_list) env.discard(None) @@ -134,6 +133,8 @@ if list_len > 0: proc.kill() print('TimeoutExpired: notify user:' + username) else: - print('Not send GUI notification: [', argv[1], argv[2], ']. Nobody logged-in with GUI. Nothing to do.') - -stdout.flush() + print( + 'Not send GUI notification: [', + argv[1], + argv[2], + ']. Nobody logged-in with GUI. Nothing to do.')