From 3faa07ba957a26ef69d3e12c4c7e8b5cdd09c043 Mon Sep 17 00:00:00 2001 From: Alexey Avramov Date: Mon, 19 Nov 2018 23:07:17 +0900 Subject: [PATCH] fix low mem warn slowdown --- Makefile | 4 ++ nohang | 25 ++++++------- nohang_notify_low_mem | 87 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 102 insertions(+), 14 deletions(-) create mode 100755 nohang_notify_low_mem diff --git a/Makefile b/Makefile index 591e414..3e5ef62 100644 --- a/Makefile +++ b/Makefile @@ -8,6 +8,9 @@ install: install -d $(DESTDIR)/$(PREFIX)/usr/sbin install -m0755 ./nohang $(DESTDIR)/$(PREFIX)/usr/sbin/nohang + install -d $(DESTDIR)/$(PREFIX)/usr/sbin + install -m0755 ./nohang_notify_low_mem $(DESTDIR)/$(PREFIX)/usr/sbin/nohang_notify_low_mem + install -d $(DESTDIR)/$(PREFIX)/etc/nohang install -m0644 ./nohang.conf $(DESTDIR)/$(PREFIX)/etc/nohang install -m0644 ./default_values_backup.conf $(DESTDIR)/$(PREFIX)/etc/nohang @@ -23,6 +26,7 @@ uninstall: # 'make uninstall' must not fail with error if systemctl is unavailable or returns error systemctl disable nohang.service || true rm -fv $(PREFIX)/usr/sbin/nohang + rm -fv $(PREFIX)/usr/sbin/nohang_notify_low_mem rm -fv $(PREFIX)/usr/share/man/man1/nohang.1.gz rm -fv $(PREFIX)/lib/systemd/system/nohang.service rm -fvr $(PREFIX)/etc/nohang/ diff --git a/nohang b/nohang index 55ed22f..77bc0a3 100755 --- a/nohang +++ b/nohang @@ -204,35 +204,33 @@ def pid_to_name(pid): def send_notify_warn(): + # find process with max badness fat_tuple = fattest() + pid = fat_tuple[1] + name = fat_tuple[0] if mem_used_zram > 0: - title = 'Low memory: {}% {}% {}%'.format( + low_mem_percent = '{}% {}% {}%'.format( round(mem_available / mem_total * 100), round(swap_free / (swap_total + 0.1) * 100), round(mem_used_zram / mem_total * 100)) elif swap_free > 0: - title = 'Low memory: {}% {}%'.format( + low_mem_percent = '{}% {}%'.format( round(mem_available / mem_total * 100), round(swap_free / (swap_total + 0.1) * 100)) else: - title = 'Low memory: {}%'.format( + low_mem_percent = '{}%'.format( round(mem_available / mem_total * 100)) - body = 'Fattest process: {}, {}'.format(fat_tuple[1], fat_tuple[0]) + title = 'Low memory: {}'.format(low_mem_percent) + body = 'Fattest process: {}, {}'.format(pid, name) if root: - # отправляем уведомление всем залогиненным пользователям - b = root_notify_env() - if len(b) > 0: - for i in b: - username, display_env, dbus_env = i[0], i[1], i[2] - Popen(['sudo', '-u', username, 'env', display_env, - dbus_env, 'notify-send', '--icon=dialog-warning', - '{}'.format(title), '{}'.format(body)]) + # send notification to all active users + Popen(['/usr/sbin/nohang_notify_low_mem', '--mem', low_mem_percent, '--pid', pid, '--name', name]) else: # отправляем уведомление пользователю, который запустил nohang - Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)]) + Popen(['notify-send', '--icon=dialog-warning', 'Low memory: {}'.format(title), '{}'.format(body)]) def send_notify(signal, name, pid): @@ -1515,4 +1513,3 @@ while True: stdout.flush() sleep_after_check_mem() - diff --git a/nohang_notify_low_mem b/nohang_notify_low_mem new file mode 100755 index 0000000..53ff4ff --- /dev/null +++ b/nohang_notify_low_mem @@ -0,0 +1,87 @@ +#!/usr/bin/env python3 + +# notify_low_mem --mem '14% 12%' --name 'stress' --pid '6666' + +# output: +# Low memory: 14% 12% +# Fattest process: 6666, stress + +from argparse import ArgumentParser +from subprocess import Popen, PIPE + +parser = ArgumentParser() + +parser.add_argument( + '--mem', + help="""available memory percent (15%, for example)""", + default=None, + type=str +) + +parser.add_argument( + '--pid', + help="""pid""", + default=None, + type=str +) + +parser.add_argument( + '--name', + help="""process name""", + default=None, + type=str +) + +args = parser.parse_args() + +pid = args.pid +name = args.name +mem = args.mem + +title = 'Low memory: {}'.format(mem) + +body = 'Fattest process: {}, {}'.format(pid, name) + +# return list of tuples with +# username, DISPLAY and DBUS_SESSION_BUS_ADDRESS +def root_notify_env(): + + ps_output_list = Popen(['ps', 'ae'], stdout=PIPE + ).communicate()[0].decode().split('\n') + + lines_with_displays = [] + for line in ps_output_list: + if ' DISPLAY=' in line and ' DBUS_SESSION_BUS_ADDRES' \ + 'S=' in line and ' USER=' in line: + lines_with_displays.append(line) + + # list of tuples with needments + deus = [] + for i in lines_with_displays: + for i in i.split(' '): + if i.startswith('USER='): + user = i.strip('\n').split('=')[1] + continue + if i.startswith('DISPLAY='): + disp_value = i.strip('\n').split('=')[1][0:2] + disp = 'DISPLAY=' + disp_value + continue + if i.startswith('DBUS_SESSION_BUS_ADDRESS='): + dbus = i.strip('\n') + deus.append(tuple([user, disp, dbus])) + + # unique list of tuples + vult = [] + for user_env_tuple in set(deus): + vult.append(user_env_tuple) + + return vult + +b = root_notify_env() + +if len(b) > 0: + for i in b: + username, display_env, dbus_env = i[0], i[1], i[2] + Popen(['sudo', '-u', username, 'env', display_env, + dbus_env, 'notify-send', '--icon=dialog-warning', + '{}'.format(title), '{}'.format(body)])