19

I am trying to write a script that will shut down the computer if a few requirements are filled with the command

os.system("poweroff")

also tried

os.system("shutdown now -h")

and a few others. but nothing happens when I run it, the computer goes through the code without crashing or producing any error messages and terminates the script normally, without shutting down the computer.

How does one shutdown a computer using python?

EDIT: Seems that the commands I have tried requires root access. Is there any way to shut down the machine from the script without elevated privileges?

ShadowCrafter_01
  • 533
  • 4
  • 19
user3522859
  • 193
  • 1
  • 1
  • 6
  • 3
    `poweroff` and `shutdown` requires privileges. Which user are you using to execute the script? – fedorqui Apr 11 '14 at 13:01
  • I have been running it as a "normal user"... thanks, will edit the question to reflect that the solution should work without root access – user3522859 Apr 11 '14 at 13:05
  • You can't shutdown the system with normal user privileges. What is your ultimate goal? – Joni Apr 11 '14 at 13:06
  • Well you can also use `sudo`, but still you need to get privileges through sudoers. Note that shutting down a computer is a thing to be restricted to trusted users, by obvious reasons. – fedorqui Apr 11 '14 at 13:08
  • 1
    If you script does other stuff as well that shouldn't run privileged, you may want to look into [polkit](http://en.wikipedia.org/wiki/Polkit) or sudo. If you're on a distro that uses systemd, its APIs may also help you - by default, it respects shutdown requests from a non-privileged user if they're the only user logged in. In any case, you always at least need *help* from something that runs privileged (systemd and polkit are long-running privileged processes with dbus apis, sudo and su are setuid root binaries), since shutdown *is* a privileged operation. – lvc Apr 11 '14 at 13:11
  • 1
    ok, thanks. The ultimate goal was to have the script shut down the computer after completing a time-consuming task, so as to save it from overheating ;) ..... running it as sudo will work for my requirements – user3522859 Apr 11 '14 at 13:12

10 Answers10

26
import os
os.system("shutdown now -h")

execute your script with root privileges.

Rahul R Dhobi
  • 5,668
  • 1
  • 29
  • 38
22

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:

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:

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

Savir
  • 17,568
  • 15
  • 82
  • 136
  • 3
    @black: Come again? *familiar* as in not too serious? If that's the case, then yeah. Programming is fun! And exciting!!! And cool **:-)** – Savir Dec 07 '14 at 23:09
  • 1
    I was referring to DaveHax actually. No worries – edmz Dec 08 '14 at 17:00
9

The best way to shutdown a system is to use the following codes

import os
os.system('systemctl poweroff') 
Sushin Pv
  • 1,826
  • 3
  • 22
  • 36
3

any way to shut down...without elevated privileges?

No, there isn't (fortunately!).

Keep in mind that you can use several system features to make privilege escalation for normal users easier:

Brian Cain
  • 14,403
  • 3
  • 50
  • 88
3

Just to add to @BorrajaX 's answer for those using logind (newer fedora systems):

import dbus
sys_bus = dbus.SystemBus()
lg = sys_bus.get_object('org.freedesktop.login1','/org/freedesktop/login1')
pwr_mgmt =  dbus.Interface(lg,'org.freedesktop.login1.Manager')
shutdown_method = pwr_mgmt.get_dbus_method("PowerOff")
shutdown_method(True)
Roeften
  • 416
  • 3
  • 7
2

linux:

import subprocess
cmdCommand = "shutdown -h now"
process = subprocess.Popen(cmdCommand.split(), stdout=subprocess.PIPE)

Windows:

import subprocess
cmdCommand = "shutdown -s"
process = subprocess.Popen(cmdCommand.split(), stdout=subprocess.PIPE)
Ali Nemati
  • 184
  • 5
2

In case you want to execute it from root, @Rahul R Dhobi answer works great:

import os
os.system("shutdown now -h")

Execution: sudo python_script.py


In case you need to execute it without root privileges:
import subprocess
import shlex
cmd = shlex.split("sudo shutdown -h now")
subprocess.call(cmd)

Execution: $ python_script.py # no sudo required

Javi
  • 913
  • 2
  • 13
  • 15
0

try this

import os
os.system("sudo shutdown now -h")

this worked for me

Hamid
  • 1,493
  • 2
  • 18
  • 32
-1

I'am using Fedora and it works with me. all what i need to do is Writing this line in terminal :

$ sudo python  yourScript.py
Black Kinght
  • 55
  • 1
  • 10
-2

There is a way to shut down the computer without using elevated permissions.

import os
subprocess.call(['osascript', '-e', 'tell app "system events" to shut down'])
Sachith Muhandiram
  • 2,819
  • 10
  • 45
  • 94