3

I love to abuse my laptop battery by using my laptop for quite some time (up to 25 minutes) even after the battery meter hits 0%.

However, sometimes I forget about that or I am just away. This causes hard shutdown, which holds the potential to corrupt the filesystem.

What is the best way to tell the computer to automatically hibernate 15 minutes after the battery reports it's empty? My idea is to write a Ruby or Bash script that would periodically poll the appropriate /proc/ subystem, but I'm wondering whether there is anything in-built.

Rok Kralj
  • 346

2 Answers2

2

I won't give you a lecture about your battery since you yourself used the word 'abuse' :).

One way of doing this would be something like this:

#!/usr/bin/env bash

while [ $(acpi | awk '{print $NF}' | sed 's/%//') -gt 0 ]; do
    ## Wait for a minute
    sleep 60s
done

## The loop above will exit when the battery level hits 0.
## When that happens, issue the shitdown command to be run in 15 minutes
shutdown -h +15

You could add that to /etc/crontab to be run by root.

terdon
  • 242,166
  • 1
    Great then! :) Just instead of using the non-standard acpi command, there's a file /sys/class/power_supply/BAT0/charge_now. – Rok Kralj Sep 18 '13 at 18:47
1

For anyone wanting a similar functionality, here is a Ruby script.

It supports multiple suspends in a row (depletion, suspend, charge, depletion, suspend, ...) and is as robust as possible.

Now it also supports libnotify, so you get a notification every minute.

#!/usr/bin/ruby
    require 'eventmachine'
    require 'libnotify'

    period = 40 # poll evey N seconds
    limit = (ARGV[0] || 20).to_i # allow usage N minutes after depletion

    def get(prop)
        File.read("/sys/class/power_supply/BAT0/#{prop}").chomp
    end

    def capacity
        get(:charge_now).to_i
    end

    def onBattery?
        get(:status) != 'Charging'
    end

    def action!
        `sync`
        `systemctl suspend`
    end

    puts 'Starting battery abuse agent.'

    EM.run {
        ticks = 0
        EM.add_periodic_timer(period) {
            if capacity == 0 && onBattery?
                ticks += 1
                if ticks % 5 == 0
                    Libnotify.show summary: 'Baterry being abused',
                        body: "for #{period*ticks} seconds.", timeout: 7.5
                end
            else
                ticks = [ticks-1, 0].max
            end
            if ticks*period > limit*60
                action!
            end
        }
    }
Rok Kralj
  • 346
  • Please accept one of the answers (yours or mine, whichever actually works for you, it is fine to accept your own answer) so the question can be marked as answered. – terdon Sep 19 '13 at 13:41