fix GUI notifications

This commit is contained in:
Alexey Avramov 2018-08-05 06:01:59 +09:00
parent 6550822554
commit c9db115908
3 changed files with 31 additions and 61 deletions

View File

@ -57,8 +57,6 @@ $ETC proc_name /// some command
- low memory warnings - low memory warnings
gui_notifications = False gui_notifications = False
notify_options =
root_display = :0
gui_low_memory_warnings = False gui_low_memory_warnings = False
min_time_between_warnings = 20 min_time_between_warnings = 20
mem_min_warnings = 20 % mem_min_warnings = 20 %

75
nohang
View File

@ -9,7 +9,6 @@ from time import sleep, time
from argparse import ArgumentParser from argparse import ArgumentParser
from sys import stdout from sys import stdout
from subprocess import Popen, PIPE
sig_dict = {signal.SIGKILL: 'SIGKILL', sig_dict = {signal.SIGKILL: 'SIGKILL',
signal.SIGTERM: 'SIGTERM'} signal.SIGTERM: 'SIGTERM'}
@ -204,38 +203,38 @@ def pid_to_name(pid):
def send_notify_warn(): def send_notify_warn():
title = 'LOW MEMORY'
if mem_used_zram > 0: if mem_used_zram > 0:
info = '"<i>MemAvailable:</i> <b>{} MiB</b>\n<i>SwapFree:</i> <b>{} MiB</b>\n<i>MemUsedZram:</i> <b>{} MiB</b>" &'.format( body = '<i>Mem Available:</i> <b>{} MiB</b>\n<i>Swap Fre' \
'e:</i> <b>{} MiB</b>\n<i>MemUsedZram:</i> <b>{} MiB</b>'.format(
kib_to_mib(mem_available), kib_to_mib(mem_available),
kib_to_mib(swap_free), kib_to_mib(swap_free),
kib_to_mib(mem_used_zram)) kib_to_mib(mem_used_zram))
elif swap_free > 0: elif swap_free > 0:
info = '"<i>MemAvailable:</i> <b>{} MiB</b>\n<i>SwapFree:</i>' \ body = '<i>Mem Available:</i> <b>{} MiB</b>\n<i>Swap Free:</i>' \
' <b>{} MiB</b>" &'.format( ' <b>{} MiB</b>'.format(
kib_to_mib(mem_available), kib_to_mib(mem_available),
kib_to_mib(swap_free)) kib_to_mib(swap_free))
else: else:
info = '"<i>MemAvailable:</i> <b>{} MiB</b>, <b>{} %</b>" &'.format( body = '<b>Mem Available: {} %</b>'.format(
kib_to_mib(mem_available), #kib_to_mib(mem_available),
round(mem_available / mem_total * 100, 1)) round(mem_available / mem_total * 100))
if root: if root:
# отправляем уведомления всем залогиненным # отправляем уведомление всем залогиненным пользователям
for uid in os.listdir('/run/user'): b = root_notify_env()
root_notify_command = 'sudo -u {} DISPLAY={} notify-s' \ if len(b) > 0:
'end {} "Warning: Low Memory" '.format( for i in b:
users_dict[uid], root_display, notify_options) username, display_env, dbus_env = i[0], i[1], i[2]
os.system(root_notify_command + info) Popen(['sudo', '-u', username, 'env', display_env,
dbus_env, 'notify-send', '--icon=dialog-warning',
'{}'.format(title), '{}'.format(body)])
else: else:
# отправляем уведомление пользователю, который запустил nohang # отправляем уведомление пользователю, который запустил nohang
user_notify_command = 'notify-send {} "Warning: Low Memory" '.format( Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)])
notify_options)
os.system(user_notify_command + info)
def send_notify(signal, name, pid, oom_score, vm_rss, vm_swap): def send_notify(signal, name, pid, oom_score, vm_rss, vm_swap):
head = 'Preventing OOM' title = 'Nohang TRIGGERED'
body = '<u>Nohang</u> sent <u>{}</u> \nto the process <b>{}</b> \n<i>P' \ body = '<u>Nohang</u> sent <u>{}</u> \nto the process <b>{}</b> \n<i>P' \
'id:</i> <b>{}</b> \n<i>Badness:</i> <b>{}</b> \n<i>VmRSS:</i> <b' \ 'id:</i> <b>{}</b> \n<i>Badness:</i> <b>{}</b> \n<i>VmRSS:</i> <b' \
'>{} MiB</b> \n<i>VmSwap:</i> <b>{} MiB</b>'.format( '>{} MiB</b> \n<i>VmSwap:</i> <b>{} MiB</b>'.format(
@ -248,10 +247,10 @@ def send_notify(signal, name, pid, oom_score, vm_rss, vm_swap):
username, display_env, dbus_env = i[0], i[1], i[2] username, display_env, dbus_env = i[0], i[1], i[2]
Popen(['sudo', '-u', username, 'env', display_env, Popen(['sudo', '-u', username, 'env', display_env,
dbus_env, 'notify-send', '--icon=dialog-warning', dbus_env, 'notify-send', '--icon=dialog-warning',
'{}'.format(head), '{}'.format(body)]) '{}'.format(title), '{}'.format(body)])
else: else:
# отправляем уведомление пользователю, который запустил nohang # отправляем уведомление пользователю, который запустил nohang
Popen(['notify-send', '{}'.format(head), '{}'.format(body)]) Popen(['notify-send', '--icon=dialog-warning', '{}'.format(title), '{}'.format(body)])
def sleep_after_send_signal(signal): def sleep_after_send_signal(signal):
@ -365,26 +364,22 @@ def find_victim_and_send_signal(signal):
else: else:
try: # SUCCESS -> RESPONSE TIME try: # delta_sucess -> response_time
os.kill(int(pid), signal) os.kill(int(pid), signal)
delta_success = time() - time0
success_time = time()
delta_success = success_time - time0
send_result = 'signal received; response time: {} ms'.format(round(delta_success * 1000)) send_result = 'signal received; response time: {} ms'.format(round(delta_success * 1000))
if gui_notifications: if gui_notifications:
send_notify(signal, name, pid, oom_score, vm_rss, vm_swap) send_notify(signal, name, pid, oom_score, vm_rss, vm_swap)
except FileNotFoundError: except FileNotFoundError:
success_time = time() delta_success = time() - time0
delta_success = success_time - time0
send_result = 'no such process; response time: {} ms'.format(round(delta_success * 1000)) send_result = 'no such process; response time: {} ms'.format(round(delta_success * 1000))
except ProcessLookupError: except ProcessLookupError:
success_time = time() delta_success = time() - time0
delta_success = success_time - time0
send_result = 'no such process; response time: {} ms'.format(round(delta_success * 1000)) send_result = 'no such process; response time: {} ms'.format(round(delta_success * 1000))
preventing_oom_message = ' Finding the process with the highest badness\n Victim is {}, pid: {}, badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Sending {} to the victim; {}'.format(name, pid, oom_score, vm_rss, vm_swap, sig_dict[signal], send_result) preventing_oom_message = ' Finding the process with the highest badness\n Victim is {}, pid: {}, badness: {}, VmRSS: {} MiB, VmSwap: {} MiB\n Sending {} to the victim; {}'.format(name, pid, oom_score, vm_rss, vm_swap, sig_dict[signal], send_result)
print(preventing_oom_message) print(preventing_oom_message)
@ -907,13 +902,7 @@ if 'gui_notifications' in config_dict:
gui_notifications = config_dict['gui_notifications'] gui_notifications = config_dict['gui_notifications']
if gui_notifications == 'True': if gui_notifications == 'True':
gui_notifications = True gui_notifications = True
users_dict = dict() from subprocess import Popen, PIPE
with open('/etc/passwd') as f:
for line in f:
line_list = line.split(':')
username = line_list[0]
uid = line_list[2]
users_dict[uid] = username
elif gui_notifications == 'False': elif gui_notifications == 'False':
gui_notifications = False gui_notifications = False
else: else:
@ -926,11 +915,8 @@ else:
exit() exit()
notify_options = conf_parse_string('notify_options')
root_display = conf_parse_string('root_display')
regex_matching = conf_parse_bool('regex_matching') regex_matching = conf_parse_bool('regex_matching')
if regex_matching: if regex_matching:
@ -1392,7 +1378,7 @@ while True:
if mem_available <= mem_min_sigkill_kb and swap_free <= swap_min_sigkill_kb: if mem_available <= mem_min_sigkill_kb and swap_free <= swap_min_sigkill_kb:
time0 = time() time0 = time()
mem_info = 'TRIGGERED!\n MemAvailable ({} MiB, {} %) < mem_min_sigkill ({} MiB, {} %)\n Swa' \ mem_info = 'TRIGGERED!\n MemAvailable ({} MiB, {} %) < mem_min_sigkill ({} MiB, {} %)\n Swa' \
'pFree ({} MiB, {} %) < swap_min_sigkill ({} MiB, {} %)'.format( 'pFree ({} MiB, {} %) < swap_min_sigkill ({} MiB, {} %)'.format(
kib_to_mib(mem_available), kib_to_mib(mem_available),
percent(mem_available / mem_total), percent(mem_available / mem_total),
@ -1412,7 +1398,7 @@ while True:
elif mem_used_zram >= zram_max_sigkill_kb: elif mem_used_zram >= zram_max_sigkill_kb:
time0 = time() time0 = time()
mem_info = 'TRIGGERED!\n MemUsedZram ({} MiB, {} %) > zram_max_sigkill ({} MiB, {} %)'.format( mem_info = 'TRIGGERED!\n MemUsedZram ({} MiB, {} %) > zram_max_sigkill ({} MiB, {} %)'.format(
kib_to_mib(mem_used_zram), kib_to_mib(mem_used_zram),
percent(mem_used_zram / mem_total), percent(mem_used_zram / mem_total),
kib_to_mib(zram_max_sigkill_kb), kib_to_mib(zram_max_sigkill_kb),
@ -1425,7 +1411,7 @@ while True:
time0 = time() time0 = time()
mem_info = 'TRIGGERED!\n MemAvailable ({} MiB, {} %) < mem_min_sigterm ({} MiB, {} %)\n Sw' \ mem_info = 'TRIGGERED!\n MemAvailable ({} MiB, {} %) < mem_min_sigterm ({} MiB, {} %)\n Sw' \
'apFree ({} MiB, {} %) < swap_min_sigterm ({} MiB, {} %)'.format( 'apFree ({} MiB, {} %) < swap_min_sigterm ({} MiB, {} %)'.format(
kib_to_mib(mem_available), kib_to_mib(mem_available),
percent(mem_available / mem_total), percent(mem_available / mem_total),
@ -1450,7 +1436,7 @@ while True:
elif mem_used_zram >= zram_max_sigterm_kb: elif mem_used_zram >= zram_max_sigterm_kb:
time0 = time() time0 = time()
mem_info = 'TRIGGERED!\n MemUsedZram ({} MiB, {} %) > zram_max_sigter' \ mem_info = 'TRIGGERED!\n MemUsedZram ({} MiB, {} %) > zram_max_sigter' \
'm ({} M, {} %)'.format( 'm ({} M, {} %)'.format(
kib_to_mib(mem_used_zram), kib_to_mib(mem_used_zram),
percent(mem_used_zram / mem_total), percent(mem_used_zram / mem_total),
@ -1476,3 +1462,4 @@ while True:
else: else:
stdout.flush() stdout.flush()
sleep_after_check_mem() sleep_after_check_mem()

View File

@ -201,21 +201,6 @@ $ETC proc_name /// some command
gui_notifications = False gui_notifications = False
Additional options for notify-send.
See `notify-send --help` and read `man notify-send`
For example:
notify_options = -u "critical"
notify_options = -t "20000" -i "dialog-warning"
notify_options =
Переменая окружения $DISPLAY, передаваемая notify-send при
запуске nohang с uid = 0.
Должен совпадать с выводом
$ echo $DISPLAY
root_display = :0
Enable GUI notifications about the low level of available memory. Enable GUI notifications about the low level of available memory.
Для работы опции должны быть включены десктопные уведомления. Для работы опции должны быть включены десктопные уведомления.
Valid values are True and False. Valid values are True and False.