Il modo migliore per arrestare un sistema è usare i seguenti codici
import os
os.system('systemctl poweroff')
Molte delle distribuzioni Linux là fuori richiedono privilegi di super utente per eseguire shutdown
o halt
, ma allora, come mai se sei seduto sul tuo computer puoi spegnerlo senza essere root? Apri un menu, premi Spegni e si spegne senza che tu diventi root
, giusto?
Beh... la motivazione dietro a questo c'è che se hai accesso fisico al computer, potresti praticamente staccare il cavo di alimentazione e spegnerlo comunque, quindi al giorno d'oggi molte distribuzioni consentono lo spegnimento tramite l'accesso al bus di sistema locale accessibile tramite dbus
. Problema con dbus
(o piuttosto i servizi esposti attraverso di essa)? È in continua evoluzione. Consiglierei di installare uno strumento visualizzatore dbus come D-feet (tieni presente:è ancora piuttosto difficile da visualizzare, ma potrebbe essere d'aiuto)
Dai un'occhiata a questi script di spegnimento di Dbus.
Se hai ancora HAL nella tua distribuzione (sta per essere deprecato) prova questo:
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()
Funziona su Ubuntu 12.04 (ho appena spento il computer per assicurarmi che funzionasse). Se hai qualcosa di più nuovo... beh, potrebbe non funzionare. È lo svantaggio di questo metodo:è molto specifico per la distribuzione.
Potrebbe essere necessario installare dbus-python
pacchetto affinché funzioni (http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html)
AGGIORNAMENTO 1:
Ho fatto un po' di ricerche e sembra che questo sia fatto nelle nuove versioni di Ubuntu tramite ConsoleKit. Ho testato il codice qui sotto nel mio Ubuntu 12.04 (che ha l'HAL deprecato e il nuovo ConsoleKit) e ha spento il mio computer:
>>> 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()
AGGIORNAMENTO 2:
Probabilmente perché puoi farlo senza essere root
merita una spiegazione un po' più ampia. Concentriamoci sul nuovo ConsoleKit
(HAL
è molto più complicato e disordinato, IMHO).
Il ConsoleKit
è un servizio in esecuzione come root
nel tuo sistema:
[email protected]:/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
Ora, d-bus
è solo un sistema di scambio di messaggi. Hai un servizio, come ConsoleKit che espone un'interfaccia a d-bus
. Uno dei metodi esposti è il Stop
(mostrato sopra). ConsoleKit i permessi di sono controllati con PolKit , che (nonostante sia basato su normali autorizzazioni Linux) offre un controllo un po' più preciso per "chi può fare cosa" . Ad esempio, PolKit può dire cose come "Se l'utente è connesso al computer, consentigli di fare qualcosa. Se è connesso in remoto, non farlo." . Se PolKit determina che il tuo utente è autorizzato a chiamare ConsoleKit è Stop
metodo, tale richiesta verrà passata da (o attraverso ) d-bus
a ConsoleKit (che successivamente spegnerà il tuo computer perché può... perché ne vale la pena... perché è root
)
Ulteriori letture:
- Cosa sono ConsoleKit e PolicyKit? Come funzionano?
- ArchWiki PolKit
Per riassumere:non puoi spegnere un computer senza essere root
. Ma puoi dire a un servizio che è in esecuzione come root
per spegnere il sistema per te.
AGGIORNAMENTO 3:
A dicembre 2021, sette anni dopo che la risposta originale era stata scritta, ho dovuto farlo di nuovo. Questa volta, in Ubuntu 18.04.
Non sorprende che le cose sembrino leggermente cambiate:
- La funzionalità PowerOff sembra essere gestita tramite un nuovo
org.freedesktop.login1
servizio, che fa parte del """nuovo""" (cough! cough!) SystemD macchine . - Il
dbus
Il pacchetto Python sembra essere stato deprecato e/o considerato "legacy". C'è, tuttavia, una nuova libreria PyDbus da utilizzare al suo posto.
Quindi possiamo ancora spegnere le macchine con uno script non privilegiato:
#! /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'
Aggiornamento 3.1:
Sembra che non sia come nuovo come pensavo X-D
C'è già una risposta di @Roeften in questo stesso thread.
BONUS :
Ho letto in uno dei tuoi commenti che vuoi spegnere il computer dopo un'attività che richiede tempo per evitare che si surriscaldi... Sapevi che probabilmente puoi accenderlo in un determinato momento utilizzando RTC? (Vedi questo e questo) Abbastanza bello, uh? (Mi sono così emozionato quando ho scoperto che potevo farlo... ) :-D
import os
os.system("shutdown now -h")
esegui il tuo script con i privilegi di root.
c'è un modo per chiudere... senza privilegi elevati?
No, non c'è (per fortuna!).
Tieni presente che puoi utilizzare diverse funzionalità di sistema per semplificare l'escalation dei privilegi per gli utenti normali:
sudo
setuid
setcap