5

My old laptop has a faulty battery, which shows 100% when on AC power but when unplugged it dramatically drops to random percentages within seconds and makes the machine turn off brutally. I am afraid of damaging my SSD (and my HDD) on which Ubuntu is loaded.

I wanted to turn the PC off as soon as the AC power is not available. I searched here and found this. But I don't understand the answer for that question or atleast it is relevant to my situation.

Please explain me a way to shut down my laptop automatically as soon as the AC power is unplugged or when there is a power failure.

  • Possible duplicate of Automatically reduce brightness on battery in Ubuntu 15.10?- his solution isn't the same, but achieves what you want- running a script when AC is unplugged. – negusp Nov 28 '16 at 14:53
  • @PatrickNegus Good job finding one of my scripts ;) – Sergiy Kolodyazhnyy Nov 28 '16 at 14:58
  • 2
    Hi,Nuwan. I'll write a script to do what you ask, once i get back to my Ubuntu setup. This should be fairly simple task to achieve. – Sergiy Kolodyazhnyy Nov 28 '16 at 15:00
  • @Serg thank you very much for your kind support, and waiting for the result. :) – Nuwan Thisara Nov 28 '16 at 15:16
5

Create a new rule in udev by opening the terminal and using:

gksu gedit /etc/udev/rules.d/50-ac-unplugged.rules

(If you are using Ubuntu 18.04 or a newer version gksu will not be available by default. In that situation please refer this question or use the above command as sudo -H gedit /etc/udev/rules.d/50-ac-unplugged.rules)

Put in the following line:

SUBSYSTEM=="power_supply", ENV{POWER_SUPPLY_ONLINE}=="0", RUN+="/sbin/shutdown now"

Save the file and then restart udev services with:

sudo udevadm control --reload-rules

Save all your work and unplug your power supply.

| improve this answer | |
  • Clever, very clever – Sergiy Kolodyazhnyy Nov 29 '16 at 7:32
  • I forgot to mentiin you need to use sudo to edit the file. – WinEunuuchs2Unix Nov 29 '16 at 20:45
  • @WinEunuuchs2Unix I actually did not try your answer because of that warning note at the end. Anyway thanks a lot for your help. thank you – Nuwan Thisara Dec 4 '16 at 2:31
  • @NuwanThisara I've revised the script with "shutdown now" and removed the note at the end which no longer applies. – WinEunuuchs2Unix Dec 5 '16 at 17:34
2

Introduction

The script that has been discussed in the comments was written in bash and a while back. Since then I have made a different implementation of it in Python and using several utility functions which use dbus. All the technical gibberish aside, the script below is basically modified version of that Python script.

The key parts of the process are all done in the main() function. The whole bunch of other lines of code are utility functions, so the code might look slightly intimidating, but it is really not and isn't doing anything spectacular. There's a few extra error-checks made just in case,too.

The idea of how it works is simple:

  1. It starts as soon as you log in.
  2. The first while loop in main waits till AC adapter is plugged in ( which in this particular case is a bit redundant, but just in case is still used). If AC adapter is plugged in we go to next step
  3. Second while loop waits till AC adapter is removed. Once it is removed, we fall through to the final step.
  4. The shutdown_system() function will try to shutdown your computer. If anything goes wrong, you should see a popup with error message.

Setting up the script

First of all, obtain the script source code and save it as a file, preferably in your home folder, in ~/bin to be exact. If you don't have bin/ folder in your home directory, create one.

Save the script as shutdown_monitor.py and make sure it is executable either via right clicking on it in file manager or using chmod +x ~/bin/shutdown_monitor.py command in terminal.

Finally, let's make the script start automatically when you log in. Open Unity Dash and find Startup Applications. Add either full path to the command orpython /home/USERNAME/bin/shutdown_monitor.py` as new command.

That's it !

Script

Also available as gist on GitHub

#!/usr/bin/env python
"""
Author: Serg Kolo <1047481448@qq.com>
Date:   Nov 29 , 2016
Purpose:Script for shutting down Ubuntu system
        if AC adapter is removed 
Written for:http://askubuntu.com/q/844193/295286  
"""
import dbus
import time
import subprocess

def get_dbus_property(bus_type, obj, path, iface, prop):
    """ utility:reads properties defined on specific dbus interface"""
    if bus_type == "session":
        bus = dbus.SessionBus()
    if bus_type == "system":
        bus = dbus.SystemBus()
    proxy = bus.get_object(obj, path)
    aux = 'org.freedesktop.DBus.Properties'
    props_iface = dbus.Interface(proxy, aux)
    props = props_iface.Get(iface, prop)
    return props

def get_dbus_method(bus_type, obj, path, interface, method, arg):
    """ utility: executes dbus method on specific interface"""
    if bus_type == "session":
        bus = dbus.SessionBus()
    if bus_type == "system":
        bus = dbus.SystemBus()
    proxy = bus.get_object(obj, path)
    method = proxy.get_dbus_method(method, interface)
    if arg:
        return method(arg)
    else:
        return method()

def on_ac_power():
    adapter = get_adapter_path()
    call = ['system','org.freedesktop.UPower',adapter,
            'org.freedesktop.UPower.Device','Online'
    ]

    if get_dbus_property(*call): return True

def get_adapter_path():
    """ Finds dbus path of the ac adapter device """
    call = ['system', 'org.freedesktop.UPower',
            '/org/freedesktop/UPower','org.freedesktop.UPower',
            'EnumerateDevices',None
    ]
    devices = get_dbus_method(*call)
    for dev in devices:
        call = ['system','org.freedesktop.UPower',dev,
                'org.freedesktop.UPower.Device','Type'
        ]
        if get_dbus_property(*call) == 1:
            return dev

def shutdown_system():
    call = ['session', 'com.canonical.Unity', 
            '/com/canonical/Unity/Session', 'com.canonical.Unity.Session', 
            'Shutdown',None
    ]
    return get_dbus_method(*call)

def main():
    while not on_ac_power():
        time.sleep(1)

    while on_ac_power():
        time.sleep(1)

    try:
        shutdown_system()
    except Exception as e:
        error_msg = 'Ooops,' + __file__ + 'failed to shutdown your system.'
        error_msg = error_msg + 'Please show Serg this error so he can fix it:'
        subprocess.call(['zenity','--error',
                         '--text', error_msg + repr(e)
        ])

if __name__ == "__main__": main()

Additional notes

Please report bugs, if you find any, preferably here in the comments or on github

| improve this answer | |
  • I did what you said but nothing happens when AC plug is removed. I think I did it correctly. Thank you – Nuwan Thisara Nov 29 '16 at 13:40
  • Hi, Nuwan. I've edited the script on github to add a few diagnostic lines. Please run it from terminal and let me know what happens. gist.github.com/SergKolo/6530ff89867e899f2b8ba728e28ad45f Try to run it as python ~/bin/shutdown_monitor.py. – Sergiy Kolodyazhnyy Nov 29 '16 at 19:41
  • Hi, Thank you for the great help. but I was not so cleaver to accomplish it. Here is what I did. Image image – Nuwan Thisara Nov 30 '16 at 13:43
  • Very good, you added it to startup applications. Did you make the file executable ? What does ls -l ~/bin/shutdown_monitor.py show ? – Sergiy Kolodyazhnyy Nov 30 '16 at 13:56
  • 1
    @NuwanThisara It uses a Unity dbus interface for shutting down, but the rest should be OK with GNOME. Maybe I'll rewrite it for GNOME but currently a bit busy, so probably won't be any time soon. It should be easy fix though. – Sergiy Kolodyazhnyy Nov 17 '18 at 9:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.