Nejlepší způsob, jak vypnout systém, je použít následující kódy
import os
os.system('systemctl poweroff')
Mnoho linuxových distribucí vyžaduje ke spuštění shutdown
oprávnění superuživatele nebo halt
, ale jak to, že když sedíte na počítači, můžete jej vypnout, aniž byste byli root? Otevřete nabídku a stiskněte Vypnout a vypne se, aniž byste se stali root
, že?
No... důvod za tím je, že pokud máte fyzický přístup k počítači, můžete do značné míry vytáhnout napájecí kabel a vypnout jej tak jako tak, takže v dnešní době mnoho distribucí umožňuje vypnutí pomocí přístupu k místní systémové sběrnici přístupné přes dbus
. Problém s dbus
(nebo spíše služby vystavené jeho prostřednictvím)? Neustále se to mění. Doporučil bych nainstalovat nástroj dbus viewer, jako je D-feet (upozorňujeme:stále je docela těžké si to představit, ale může to pomoci)
Podívejte se na tyto skripty pro vypnutí Dbus.
Pokud stále máte HAL ve své distribuci (je na cestě k ukončení podpory), zkuste toto:
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()
Funguje to na Ubuntu 12.04 (právě jsem vypnul počítač, abych se ujistil, že to funguje). Pokud máte něco novějšího... no, nemusí to fungovat. Je to nevýhoda této metody:je velmi specifická pro distribuci.
Možná budete muset nainstalovat dbus-python
balíček, aby to fungovalo (http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html)
AKTUALIZACE 1:
Dělal jsem malý průzkum a vypadá to, že se to dělá v novějších verzích Ubuntu prostřednictvím ConsoleKit. Testoval jsem níže uvedený kód v mém Ubuntu 12.04 (který má zastaralou HAL a novější ConsoleKit) a vypnul můj počítač:
>>> 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()
AKTUALIZACE 2:
Pravděpodobně proč můžete to udělat, aniž byste byli root
si zaslouží trochu širší vysvětlení. Zaměřme se na novější ConsoleKit
(HAL
je mnohem složitější a chaotický, IMHO).
ConsoleKit
je služba běžící jako root
ve vašem systému:
[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
Nyní d-bus
je pouze systém předávání zpráv. Máte službu, jako je ConsoleKit který vystavuje rozhraní d-bus
. Jednou z vystavených metod je Stop
(zobrazeno výše). ConsoleKit Oprávnění uživatele se řídí pomocí PolKit , který (navzdory tomu, že je založen na běžných linuxových oprávněních) nabízí o něco jemnější kontrolu pro „kdo může co dělat“ . Například PolKit může říkat věci jako "Pokud je uživatel přihlášen k počítači, umožněte mu něco dělat. Pokud je vzdáleně připojen, tak to nedělejte." . Pokud PolKit určuje, že váš uživatel může volat ConsoleKit 's Stop
způsob, bude tento požadavek předán (nebo prostřednictvím ) d-bus
na ConsoleKit (což následně vypne váš počítač, protože může... protože to stojí za to... protože je root
)
Další čtení:
- Co jsou ConsoleKit a PolicyKit? Jak fungují?
- ArchWiki PolKit
Abych to shrnul:Nemůžete vypnout počítač bez root
. Ale můžete říct, že služba běží jako root
k vypnutí systému za vás.
AKTUALIZACE 3:
V prosinci 2021, sedm let po napsání původní odpovědi, jsem to musel udělat znovu. Tentokrát v Ubuntu 18.04.
Není překvapením, že se zdá, že se věci trochu změnily:
- Zdá se, že funkci PowerOff ovládá nový
org.freedesktop.login1
služba, která je součástí """nové""" (kašel! kašli!) SystemD strojní zařízení . - Číslo
dbus
Zdá se, že balíček Python byl zastaralý a/nebo považován za „starší“. Existuje však nová knihovna PyDbus, kterou lze použít.
Stále tedy můžeme vypínat stroje pomocí neprivilegovaného skriptu:
#! /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'
Aktualizace 3.1:
Zdá se, že není jako nový jak jsem si myslel X-D
Odpověď od @Roeften již existuje ve stejném vlákně.
BONUS :
V jednom z vašich komentářů jsem četl, že chcete vypnout počítač po časově náročném úkonu, abyste zabránili jeho přehřátí... Věděli jste, že můžete pravděpodobně zapnout jej v daný čas pomocí RTC? (Podívejte se na toto a toto) Docela skvělé, uh? (Byl jsem tak nadšený, když jsem zjistil, že to dokážu... ) :-D
import os
os.system("shutdown now -h")
spusťte skript s právy root.
nějaký způsob vypnutí...bez zvýšených oprávnění?
Ne, není (naštěstí!).
Mějte na paměti, že můžete použít několik systémových funkcí k usnadnění eskalace oprávnění pro běžné uživatele:
sudo
setuid
setcap