#!/usr/bin/python3 import os import subprocess import sys import time # For use with systemd as a service: # copy this script to /usr/local/sbin/critical_hibernate.py with: # install -m 0755 -o root -g root critical_hibernate.py # /usr/local/sbin/critical_hibernate.py # and: # /etc/systemd/system/critical_hibernate.service # # [Service] # ExecStart=/usr/local/sbin/critical_hibernate.py # Restart=on-failure # KillMode=process # # [Install] # WantedBy=multi-user.target # # Then, do a systemctl enable --now critical_hibernate sysfs_path = '/sys/class/power_supply/BAT0/uevent' threshold = 10 run_hibernate = True original_print = print def flush_print(*args, **kw): original_print(*args, **kw) filelike = kw.get('file', sys.stdout) filelike.flush() print = flush_print try: while True: batfd = None try: batfd = os.open(sysfs_path, os.O_RDONLY) print('monitoring %s (threshold %d%%)' % (sysfs_path, threshold)) while True: uevent_dict = dict((tuple(x.strip() for x in e.split(b'=')) for e in os.pread(batfd, 1024, 0).split(b'\n') if e)) capacity = int(uevent_dict[b'POWER_SUPPLY_CAPACITY']) status = uevent_dict[b'POWER_SUPPLY_STATUS'] if status == b'Discharging' and capacity <= threshold: print('low battery %d <= %d' % (capacity, threshold)) if run_hibernate: print('running systemctl hibernate') subprocess.run(['/bin/systemctl', 'hibernate']) time.sleep(60) except OSError: print('io error on %s, assume battery changement' % sysfs_path) except FileNotFoundError: print('file %s is missing' % sysfs_path) finally: if batfd is not None: os.close(batfd) print('retrying to open %s in 60 seconds' % sysfs_path) time.sleep(60) except KeyboardInterrupt: print('SIGINT, exiting')