Ответ 1
Во многих дистрибутивах Linux требуются привилегии суперпользователя для выполнения shutdown
или halt
, но почему же, если вы сидите за своим компьютером, вы можете отключить его, не будучи пользователем root? Вы открываете меню, нажимаете "Выключение", и оно выключается, и вы не становитесь root
, верно?
Что ж... обоснование этого заключается в том, что если у вас есть физический доступ к компьютеру, вы можете в значительной степени отключить шнур питания и отключить его в любом случае, поэтому в настоящее время многие дистрибутивы позволяют отключать питание, хотя доступ к локальной системной шине доступен до dbus
. Проблема с dbus
(или сервисы, выставленные через него, скорее)? Это постоянно меняется. Я бы порекомендовал установить средство просмотра dbus, такое как D-футы (имейте в виду: это все еще довольно сложно визуализировать, но это может помочь)
Посмотрите эти сценарии отключения Dbus.
Если у вас все еще есть HAL в вашем дистрибутиве (на пути к устареванию), попробуйте это:
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()
Это работает на Ubuntu 12.04 (я просто выключил компьютер, чтобы убедиться, что он работает). Если у вас есть что-то более новое... ну, это может не сработать. Недостаток этого метода: он очень специфичен для распределения.
Возможно, вам придется установить пакет dbus-python
, чтобы это работало (http://dbus.freedesktop.org/doc/dbus-python/doc/tutorial.html)
ОБНОВЛЕНИЕ 1:
Я провел небольшое исследование, и похоже, что это делается в более новых версиях Ubuntu через ConsoleKit. Я протестировал приведенный ниже код в своем Ubuntu 12.04 (в котором устаревший HAL и более новый ConsoleKit), и он отключил мой компьютер:
>>> 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()
ОБНОВЛЕНИЕ 2:
Вероятно, почему вы можете сделать это, не будучи root
, заслуживает немного более широкого объяснения. Давайте сосредоточимся на более новом ConsoleKit
(HAL
намного сложнее и грязнее, ИМХО).
ConsoleKit
- это служба, работающая как root
в вашей системе:
[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
Теперь d-bus
- это просто система передачи сообщений. У вас есть сервис, такой как ConsoleKit, который предоставляет интерфейс для d-bus
. Одним из представленных методов является Stop
(показано выше). Разрешения ConsoleKit контролируются с помощью PolKit, который (несмотря на то, что он основан на обычных разрешениях Linux) предлагает более тонкий контроль над тем, "кто может делать что". Например, PolKit может сказать что-то вроде: "Если пользователь вошел в компьютер, то разрешите ему что-то сделать. Если он подключен удаленно, то нет". Если PolKit определит, что вашему пользователю разрешено вызывать метод ConsoleKit Stop
, этот запрос будет передан (или через) d-bus
в ConsoleKit (который впоследствии отключит ваш компьютер, потому что он может... потому что это того стоит). потому что это root
)
Дальнейшее чтение:
Подводя итог: Вы не можете выключить компьютер, не будучи root
. Но вы можете сказать службе, которая работает как root
, чтобы выключить систему для вас.
БОНУС:
Я прочитал в одном из ваших комментариев, что вы хотите выключить компьютер после трудоемкой задачи, чтобы предотвратить его перегрев... Знаете ли вы, что вы можете включить его в определенное время, используя RTC? (Смотрите это и это) Довольно круто, а? (Я так обрадовался, когда узнал, что могу это сделать...) : -D