shutting down computer (linux) using python
Many of the linux distributions out there require super user privileges to execute shutdown
or halt
, but then, how come that if you're sitting on your computer you can power it off without being root? You open a menu, hit Shutdown and it shutdowns without you becoming root
, right?
Well... the rationale behind this is that if you have physical access to the computer, you could pretty much pull the power cord and power it off anyways, so nowadays, many distributions allow power-off though access to the local System Bus accessible through dbus
. Problem with dbus
(or the services exposed through it, rather)? It's constantly changing. I'd recommend installing a dbus viewer tool such as D-feet (be advised: it's still pretty hard to visualize, but it may help)
Take a look to these Dbus shutdown scripts.
If you still have HAL in your distrubution (is on the way to being deprecated) try this:
import dbus
sys_bus = dbus.SystemBus()
hal_srvc = sys_bus.get_object('org.freedesktop.Hal',
'/org/freedesktop/Hal/devices/computer')
pwr_mgmt = dbus.Interface(hal_srvc,
'org.freedesktop.Hal.Device.SystemPowerManagement')
shutdown_method = pwr_mgmt.get_dbus_method("Shutdown")
shutdown_method()
This works on a Ubuntu 12.04 (I just powered off my computer to make sure it worked). If you have something newer... well, it may not work. It's the downside of this method: it is very distribution specific.
You might have to install the dbus-python
package for this to work (http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html)
UPDATE 1:
I've been doing a little bit of research and it looks like this is done in newer Ubuntu versions through ConsoleKit. I've tested the code below in my Ubuntu 12.04 (which has the deprecated HAL and the newer ConsoleKit) and it did shut my computer off:
>>> import dbus
>>> sys_bus = dbus.SystemBus()
>>> ck_srv = sys_bus.get_object('org.freedesktop.ConsoleKit',
'/org/freedesktop/ConsoleKit/Manager')
>>> ck_iface = dbus.Interface(ck_srv, 'org.freedesktop.ConsoleKit.Manager')
>>> stop_method = ck_iface.get_dbus_method("Stop")
>>> stop_method()
UPDATE 2:
Probably why can you do this without being root
deserves a bit of a wider explanation. Let's focus on the newer ConsoleKit
(HAL
is way more complicated and messy, IMHO).
The ConsoleKit
is a service running as root
in your system:
borrajax@borrajax:/tmp$ ps aux|grep console-kit
root 1590 0.0 0.0 1043056 3876 ? Sl Dec05 0:00 /usr/sbin/console-kit-daemon --no-daemon
Now, d-bus
is just a message passing system. You have a service, such as ConsoleKit that exposes an interface to d-bus
. One of the methods exposed is the Stop
(shown above). ConsoleKit's permissions are controlled with PolKit, which (despite on being based on regular Linux permissions) offers a bit of a finer grain of control for "who can do what". For instance, PolKit can say things like "If the user is logged into the computer, then allow him to do something. If it's remotely connected, then don't.". If PolKit determines that your user is allowed to call ConsoleKit's Stop
method, that request will be passed by (or through) d-bus
to ConsoleKit (which will subsequently shutdown your computer because it can... because it worth's it... because it's root
)
Further reading:
- What are ConsoleKit and PolicyKit? How do they work?
- ArchWiki PolKit
To summarize: You can't switch a computer off without being root
. But you can tell a service that is running as root
to shutdown the system for you.
UPDATE 3:
On December 2021, seven years after the original answer was written I had to do this again. This time, in a Ubuntu 18.04.
Unsurprisingly, things seem to have changed a bit:
- The PowerOff functionality seems to be handled via a new
org.freedesktop.login1
service, which is part of the """new""" (cough! cough!) SystemD machinery. - The
dbus
Python package seems to have been deprecated and/or considered "legacy". There is, however, a new PyDbus library to be used instead.
So we can still power off machines with an unprivileged script:
#! /usr/bin/python3
from pydbus import SystemBus
bus = SystemBus()
proxy = bus.get('org.freedesktop.login1', '/org/freedesktop/login1')
if proxy.CanPowerOff() == 'yes':
proxy.PowerOff(False) # False for 'NOT interactive'
Update 3.1:
It looks like it's not as new as I thought X-D
There's already an answer by @Roeften in this very same thread.
BONUS:
I read in one of your comments that you wanna switch the computer off after a time consuming task to prevent it from overheating... Did you know that you can probably power it on at a given time using RTC? (See this and this) Pretty cool, uh? (I got so excited when I found out I could do this... ) :-D
Fast system shutdown in Python
Using System Request (SysRq) and than calling echo b > /proc/sysrq-trigger
to immediately reboot the system, without unmounting or syncing filesystems.
import os
os.system('echo 1 > /proc/sys/kernel/sysrq && echo b > /proc/sysrq-trigger')
Check this answer for more info:
https://unix.stackexchange.com/questions/163370/is-there-a-fastest-way-to-shutdown-the-system
Shutting down computer from a python script in apache
For security reasons Apache user cannot run sudo
command.
Usually this is an almost mandatory rule to save you from attacks but for a Raspberry PI installation you may not have this problem so you can just add Apache user to sudoers (or, better, uso visudo to edit that file).
Something else? Yes you may simply add shutdown permissions to Apache user, follow this tutorial. In short you have to change /etc/sudoers
with:
%groupName ALL= NOPASSWD: /sbin/shutdown
Executing code on server while shutting down the computer
You can use screen
to maintain a session and achieve the goal that allows you to run the code on the server.
Refer to this: https://www.gnu.org/software/screen/
Some basic commands:
- Create session named RunWork
screen -S RunWork
- List all sessions:
screen -ls
- Open a session
screen -r SessionID
...
Shut down ubuntu with python
What you want is to execute the shell command sudo shutdown -h now
.
import subprocess
>password=input()
>>if password=="ThePassword":
>>>print ("Welcome")
>>>>else:
>>>>>subprocess.call(["sudo", "shutdown", "-h", "now"])
Most likely you will be prompted to enter your administrator password for this to work. You will need to run the program in sudo
mode with root permissions.
Related Topics
Is There a Built in Package to Parse HTML into Dom
Linux: Pipe into Python (Ncurses) Script, Stdin and Termios
Numpy Selecting Specific Column Index Per Row by Using a List of Indexes
What Is the Purpose of Class Methods
Python: Get a Frequency Count Based on Two Columns (Variables) in Pandas Dataframe Some Row Appers
Difference Between Exit() and Sys.Exit() in Python
Skip Rows During CSV Import Pandas
Pip Uses Incorrect Cached Package Version, Instead of the User-Specified Version
How to Find All Comments with Beautiful Soup
Pickled File Won't Load on MAC/Linux
How to Write to a CSV Line by Line
How to Pass a List as a Command-Line Argument with Argparse
Typeerror: Unhashable Type: 'Dict'
Matplotlib Make Tick Labels Font Size Smaller