2015-06-05

Auto shutdown on low battery

My window manager, Awesome, is not a desktop manager so it does not come with all the bells and whistles (and therefore start in a split of a second) but it also lacks some interesting features.
In order to prevent my laptop to die abruptly when battery is critically low and corrupting my main filesystem, I put up a tiny little simple solution: a script, run by cron, that checks if battery is low and cleanly shutdown the system when it is critically low.

So, first, the script, largely inspired by this answer.

#!/bin/sh
# touch $HOME/.dbus/Xdbus
# chmod 600 $HOME/.dbus/Xdbus
# env | grep DBUS_SESSION_BUS_ADDRESS > $HOME/.dbus/Xdbus
# echo 'export DBUS_SESSION_BUS_ADDRESS' >> $HOME/.dbus/Xdbus
# exit 0
#
if [ -r ~/.dbus/Xdbus ]; then
  . ~/.dbus/Xdbus
fi


low_threshold=6
critical_threshold=4
timeout=50
shutdown_cmd='sudo /sbin/shutdown -h now'
 

level=$(cat /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:08/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/capacity)
state=$(cat /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A08:00/device:08/PNP0C09:00/PNP0C0A:00/power_supply/BAT0/status)


if [ x"$state" != x'Discharging' ]; then
  exit 0
fi


do_shutdown() {
  sleep $timeout && kill $zenity_pid 2>/dev/null
  if [ x"$state" != x'Discharging' ]; then
    exit 0
  else
    $shutdown_cmd
  fi
}

if [ "$level" -gt $critical_threshold ] && [ "$level" -lt $low_threshold ]; then
  notify-send -u critical -t 6000 "Battery level is low: $level%"
fi

if [ "$level" -lt $critical_threshold ]; then
  notify-send -u critical -t 20000 "Battery level is low: $level%" \
    "The system is going to shut down in $timeout seconds."
  DISPLAY=:0 zenity --question --ok-label 'OK' --cancel-label 'Cancel' \
    --text "Battery level is low: $level%.\n\n The system is going to shut down in $timeout seconds." &
  zenity_pid=$!

  do_shutdown &
  shutdown_pid=$!

  trap 'kill $shutdown_pid' 1

  if ! wait $zenity_pid; then
    kill $shutdown_pid 2>/dev/null
  fi
fi


You have to adapt to the place where the battery state is on your system.
You may have to check that the battery state is really "Discharging".

You also have to add a cron job to run this script on a sufficiently regular basis. To do so :
$ crontab -e
 and add this line :
*/1 * * * * /home/me/usr/bin/auto-shutdown

This will cause the script to be run every second.

For the script to work, you'll need:
  1. To be able to shutdown your system from the command line using sudo.
  2. Have zenity and notify-send installed.
For the first point, you can add a file in /etc/sudoers.d/shutdown containing the line:
username ALL=(ALL) NOPASSWD: /sbin/shutdown

In debian, notify-send is in the libnotify-bin package.

Hope it helps.

No comments: