# Automatic standby / hibernate script

## shladnik

Hi all,

One of the things that I somehow found it lacking for a long time in gentoo is automatic standby on some timeout. I know you can get this in gnome power manager or so, but I don't use a full blown DE, just WM.

You need actmon (http://pypi.python.org/pypi/actmon/0.1). I start it via my normal user .xinitrc and I set permissions for /sys/power/state in /etc/local.d/somescript.start accordingly. Here it is:

http://www.filedropper.com/power_1

It's not a very complex thing but it does what I need. Right now I just use it to hibernate if battery is dried out entirely or if my PC is really bored for 2 hours. However, since linux is about customization, I was thinking about features like monitoring ssh sessions to finish / idle, or maybe wait for some process to end, or prevent standby while backup is running... if you could get event on user interaction, you could build up some kind of interactive CPU governor and so on. I'm not planning to do such things just for fun, but I found it strange that these things are not actually available out there at least for power users. Or there are, but I just couldn't find it?

Regards,

Stefan

UPDATE November 2012

New times, new laptop, new requirements. And above link doesn't work, so posting my current script:

- select suspend to RAM vs suspend to disk depending on battery level (disk if < 1 hour)

- suspend after 10 minutes

- suspend 1 minute before battery runs out

```

#!/usr/bin/python2

import actmon

import threading

import time

import datetime

battery_state = None

battery_event = threading.Event()

#

# Battery thread stuff

#

def parse_power_supply(dev = 'BAT1'):

  def parse_var(l):

    prefix = 'POWER_SUPPLY_'

    l = l.split(prefix, 1)[1]

    l = l.rstrip()

    name, val = l.split('=', 1)

    if val.isdigit(): val = int(val)

    return name, val

  return { k : v for k, v in ( parse_var(l) for l in open('/sys/class/power_supply/' + dev + '/uevent', 'r') ) }

class BatteryState():

  level      = None

  time2full  = None

  time2empty = None

def get_battery_state():

  info = parse_power_supply()

  state = BatteryState()

  state.level = float(info['CHARGE_NOW']) / info['CHARGE_FULL']

  if info['CURRENT_NOW']:

    if   info['STATUS'] == 'Discharging':

      state.time2empty = datetime.timedelta(hours = float(info['CHARGE_NOW']) / info['CURRENT_NOW'])

    elif info['STATUS'] == 'Charging':

      state.time2full  = datetime.timedelta(hours = float(info['CHARGE_FULL'] - info['CHARGE_NOW']) / info['CURRENT_NOW'])

    elif info['STATUS'] != 'Full':

      raise Exception("Unknown STATUS ({})".format(info['STATUS']))

  return state

def battery_evgen(): # actually just pooling

  while 1:

    global battery_state

    prev_state = battery_state

    battery_state = get_battery_state()

    if battery_state != prev_state:

      battery_event.set()

      battery_event.clear()

    time.sleep(30)

battery = threading.Thread(target = battery_evgen, name = 'BatteryThread')

battery.daemon = True

battery.start()

while 1:

  battery_event.wait(timeout = 60)

  idle = actmon.get_idle_time() / 1000.

  conditions = (

    battery_state.time2empty and battery_state.time2empty <= datetime.timedelta(minutes=5),

    battery_state.time2empty and idle > 10 * 60,

  )

  if any(conditions):

    # Before 3.6 kernel

    #saving_state = ('mem', 'disk')[battery_state.time2empty <= datetime.timedelta(minutes=60)]

    #open('/sys/power/state', 'w').write(saving_state)

    # 3.6+ kernel

    #open('/sys/power/disk' , 'w').write('suspend')

    #open('/sys/power/state', 'w').write('disk'   )

    # external script

    subprocess.call(('sudo', '/root/hibernate.py', 'fast', 'mem'))

```

UPDATE December 2012

Changes:

- 3.6 kernel introduced "hybrid sleep" (suspend to disk & ram, then wake from ram unless battery ran out)

- use drop_caches to speed up disk hibernate/resume

- hibernation into special script cause I use it via hotkey and lid open/close event:

```

#!/usr/bin/python

import sys

import subprocess

import time

fast = 'fast' in sys.argv[1:]

mem  = 'mem'  in sys.argv[1:]

if fast:

  subprocess.call(['sync'])

  open('/proc/sys/vm/drop_caches', 'w').write('3')

open('/sys/power/disk' , 'w').write(('shutdown', 'suspend')[mem])

open('/sys/power/state', 'w').write('disk')

```

- use sudo instead of permission change:

```

username[/b] ALL=(root) NOPASSWD: /root/hibernate.py

```

Last edited by shladnik on Mon Dec 24, 2012 9:32 am; edited 3 times in total

----------

## eccerr0r

Though this is not about Gnome, this would be neat for both Gnome and non-desktop environment systems...

What would be neat is how to get Gnome/KDE/... to hibernate the laptop if it was suspended for an extended period of time...

My netbook can consume the whole battery if left on suspend for more than a day or so, would be nice if it notices after 6 hours or so, nobody has tried to wake it, so it will wake itself up and suspend to disk (or rather, SSD) instead...

Useful? Not sure... but definitely would help if I forget about the suspend...

----------

## shladnik

Yes, I was thinking about that too. That shouldn't be to tough to add. Here I found some nice documentation about that:

http://www.mythtv.org/wiki/ACPI_Wakeup

However, I found suspend-to-disk fast enough for now, so I don't really need that right now. But might do something like that someday for other purposes, like nightly backups... energy prices are rising, so it might make sense even if it is not about battery life time  :Smile: 

----------

## eccerr0r

Yeah, would need some sort of mechanism like that to wake the machine up to hibernate.  I just wonder what the machine should do if a user wakes it up around that time, whether it should still just go hibernate anyway or not (or if there's an easy way to tell if a user or it's the RTC that caused the wakeup.)

But technically speaking, energy costs for a computer is pretty low, especially a laptop.  But for me, data integrity is more important, making sure the suspended machine doesn't suddenly lose its memory because the battery ran out.

----------

## smartass

pm-suspend-hybrid may be what you want, eccerr0r

----------

## eccerr0r

hmm...maybe.  Would be nice for SSDs so that it wouldn't need to write a whole image to disk if not needed.

Definitely would be nice if it could estimate how much battery is left and suspend the machine if it thinks I should have hibernated instead of suspend because I forgot...  Say, if I leave the machine suspended for more than an hour (better yet, when it estimates the battery will only have X amount left) it should just go ahead and write to disk when I forget, instead of writing to disk each time I suspend just in case I forget.

Supposedly I have pm-suspend-hybrid installed, unsure if gnome is actually using it or not..

----------

## shladnik

You could easily implement that with mine script. To disk if less than e.g. 30% mem otherwise.

----------

## shazeal

The link to your script was missing so I made my own. Its rather primitive but it works  :Smile: 

It times out after 1 hour, and skips the check if emerge or mplayer2 are running. And it also kills itself if X isnt running.

```
#!/usr/bin/python

import actmon

import os

import commands

import time

def checkProc():

    XOK = commands.getstatusoutput("ps -C X")

    if XOK == 1:

        exit()

    emergeOK = commands.getstatusoutput("ps -C emerge")

    mplayer2OK = commands.getstatusoutput("ps -C mplayer2")

    if emergeOK[0] == 0 or mplayer2OK[0] == 0:

        return False

    return True

def checkTimeout ():

    lastact = actmon.get_idle_time()

    if lastact > 3600000:

        os.system("sudo /usr/sbin/s2ram")

while True:

    time.sleep(60)

    if checkProc():

        checkTimeout()
```

----------

## shladnik

If anyone cares, here's my latest script:

https://github.com/shladnik/power.py

----------

