Сделал под свои нужды. Никаких конфигов, параметров командной строки итд :-) Хотите - берите, хотите - не берите.
Скрипт срабатывает при сетевой активности (upload+download > 50Mb / 5min), дисковой активности (IO > 25Mb/min), и активности процессора.
#!/usr/bin/env python3
'''
Monitor network traffic, disk I/O and CPU usage.
If they excel some given values, prevent computer from suspending.
Author: Joseph Botosh <rumly111@gmail.com>
License: GPLv2
'''
import time
import dbus
import logging
def int_from_file(fn : str) -> int:
with open(fn, 'rt') as f:
return int(f.readline())
class IntFile:
def __init__(self, fname):
self.fname = fname
self._last = None
self.history = []
def update(self):
n = int_from_file(self.fname)
if self._last is not None:
self.history.append(n - self._last)
self._last = n
if len(self.history) > 7200:
self.history = self.history[3600:]
def total(self, period: int):
return sum(self.history[-period:])
class CpuInfo:
def __init__(self):
self._prevstats = None
self.history = [0]
def update(self):
stats = []
with open('/proc/stat', 'rt') as f:
for l in f.readlines():
stats = l.split()
if stats[0] == 'cpu':
break
stats = [float(s) for s in stats[1:]]
# https://stackoverflow.com/questions/23367857/accurate-calculation-of-cpu-usage-given-in-percentage-in-linux
user,nice,system,idle,iowait,irq,softrig,steal,_,_ = stats
Idle = idle + iowait
NonIdle = user + nice + system + irq + softrig + steal
Total = Idle + NonIdle
if self._prevstats is not None:
ps = self._prevstats
cpu_perc = (NonIdle - ps['NonIdle']) / (Total - ps['Total']) * 100
self.history.append(cpu_perc)
self._prevstats = {'Total':Total, 'Idle':Idle, 'NonIdle':NonIdle}
if len(self.history) > 7200:
self.history = self.history[3600:]
def average(self, period : int):
return sum(self.history[-period:]) / min(len(self.history) or 1, period)
class DiskIO:
def __init__(self):
self.history = [0]
self._prevstats = None
def update(self):
stats = []
with open('/proc/diskstats', 'rt') as f:
for l in f.readlines():
stats = l.split()
if stats[2] == 'sda':
break
stats = [int(s) for s in stats[3:]]
read_bytes = stats[2] * 512
write_bytes = stats[6] * 512
if self._prevstats is not None:
ps = self._prevstats
diskio_rw = (read_bytes - ps['read']) + (write_bytes - ps['write'])
self.history.append(diskio_rw)
self._prevstats = {'read':read_bytes, 'write':write_bytes}
if len(self.history) > 7200:
self.history = self.history[3600:]
def total(self, period : int):
return sum(self.history[-period:])
class SuspendInhibitor:
def __init__(self, dbus_iface : dbus.Interface):
self.__cookie = 0
self.__enabled = False
self.__dbus_iface = dbus_iface
@property
def enabled(self):
return self.__enabled
def set_enabled(self, e: bool, msg: str = ''):
if e and not self.__enabled:
self.__cookie = self.__dbus_iface.Inhibit('DoNotSleep',0,msg,4)
self.__enabled = True
logging.info('Inhibit [msg:"{}", cookie:{}]'.format(msg,self.__cookie))
elif not e and self.__enabled:
self.__dbus_iface.Uninhibit(self.__cookie)
self.__enabled = False
logging.info('Uninhibit [cookie:{}]'.format(self.__cookie))
if __name__=='__main__':
logging.basicConfig(level=logging.INFO,
format='%(asctime)s %(message)s',
datefmt='%Y-%m-%d %H:%m:%S')
bus = dbus.SessionBus()
obj = bus.get_object('org.gnome.SessionManager','/org/gnome/SessionManager')
iface = dbus.Interface(obj, 'org.gnome.SessionManager')
net_inhibitor = SuspendInhibitor(iface)
cpu_inhibitor = SuspendInhibitor(iface)
diskio_inhibitor = SuspendInhibitor(iface)
net_down = IntFile('/sys/class/net/wlp4s0/statistics/rx_bytes')
net_up = IntFile('/sys/class/net/wlp4s0/statistics/tx_bytes')
cpu_perc = CpuInfo()
diskio_info = DiskIO()
while True:
for o in (net_down, net_up, cpu_perc, diskio_info):
o.update()
net_traffic = net_down.total(300) + net_up.total(300)
if net_traffic > 50 * 1024 * 1024:
net_inhibitor.set_enabled(True, 'Network traffic {} bytes/5min'.format(net_traffic))
else:
net_inhibitor.set_enabled(False)
cpu_perc_avg = cpu_perc.average(60)
if cpu_perc_avg > 55.0:
cpu_inhibitor.set_enabled(True, 'CPU usage average {}%/1min'.format(cpu_perc_avg))
else:
cpu_inhibitor.set_enabled(False)
diskio_bytes = diskio_info.total(60)
# logging.debug('diskio_bytes (60s) = {}'.format(diskio_bytes))
if diskio_bytes > 25 * 1024 * 1024:
diskio_inhibitor.set_enabled(True, 'Disk IO {} bytes/1min'.format(diskio_bytes))
else:
diskio_inhibitor.set_enabled(False)
time.sleep(1)