Seite 1 von 1
Linux System mit D-Bus herunterfahren
Verfasst: Donnerstag 8. April 2010, 15:33
von Ubuntuxer
Ich möchte euch eine Möglichkeit zeigen unter Linux den Computer ohne Root-Rechte herunterzufahren. Diese Lösung müsste mit jeder Distribution funktionieren.
Code: Alles auswählen
#!/usr/bin/env python
import sys, dbus
def shutdown():
bus = dbus.SystemBus()
try:
remote_object = bus.get_object('org.freedesktop.Hal',
'/org/freedesktop/Hal/devices/computer')
props = remote_object.Shutdown(dbus_interface='org.freedesktop.Hal.Device.SystemPowerManagement')
except dbus.exceptions.DBusException, e:
print e
if __name__ == "__main__":
shutdown()
Verfasst: Donnerstag 8. April 2010, 17:10
von tordmor
Das hat sogar als user nobody funktioniert.
Verfasst: Donnerstag 8. April 2010, 21:57
von snafu
tordmor hat geschrieben:
Naja, irgendwie muss man als Benutzer in der grafischen Oberfläche ja herunterfahren können. Das ist halt der Grund, warum dort nicht nach dem Passwort gefragt wird.
Verfasst: Freitag 9. April 2010, 07:18
von jens
User oder nobody ist doch irgendwie was anderes, oder?
Verfasst: Freitag 9. April 2010, 11:49
von lunar
nobody ist ein Benutzerkonto wie jedes andere. Ein spezielles "Gast"-Konto wie unter Windows gibt es nicht, nobody ist nur eine Konvention für Dienste, die keine Rechte benötigen, und hat per se nicht weniger Rechte als ein "normales" Konto.
Im Allgemeinen ist HAL auch nicht der Weg zum Herunterfahren, sondern nur der allerletzte Ausweg. Grundsätzlich muss das nicht funktionieren, denn eigentlich ist die systemweite Sitzungsverwaltung imho heute Sache von ConsoleKit. Zudem umgeht es sämtliche Sitzungsverwaltung der laufenden Desktop-Umgebung, so dass unter Umständen bei der nächsten Anmeldung die Sitzung nicht korrekt wiederhergestellt werden kann.
Man sollte also vorher immer mindestens die Sitzungsverwaltungsdienste von Gnome (org.gnome.SessionManager /org/gnome/SessionManager org.gnome.SessionManager.RequestShutdown) und KDE (org.kde.ksmserver /KSMServer org.kde.KSMServerInterface.logout) versuchen.
Verfasst: Freitag 9. April 2010, 17:59
von Ubuntuxer
Ich hab nun mal Lunars Verbesserungsvorschlag umgesetzt:
Code: Alles auswählen
#!/usr/bin/env python
import sys, dbus
import os
def shutdown():
session = os.environ['DESKTOP_SESSION']
if (session == 'gnome'):
try:
bus = dbus.SessionBus()
remote_object = bus.get_object('org.gnome.SessionManager',
'/org/gnome/SessionManager')
props = remote_object.Shutdown(dbus_interface='org.gnome.SessionManager.RequestShutdown')
except dbus.exceptions.DBusException, e:
print e
elif (session == 'kde'):
try:
bus = dbus.SessionBus()
remote_object = bus.get_object('org.kde.ksmserver', '/KSMServer')
props = remote_object.Shutdown(dbus_interface='org.kde.KSMServerInterface.logout')
except dbus.exceptions.DBusException, e:
print e
else:
try:
bus = dbus.SystemBus()
remote_object = bus.get_object('org.freedesktop.Hal',
'/org/freedesktop/Hal/devices/computer')
props = remote_object.Shutdown(dbus_interface='org.freedesktop.Hal.Device.SystemPowerManagement')
except dbus.exceptions.DBusException, e:
print e
if __name__ == "__main__":
shutdown()
EDIT: Das Code-Beispiel funktioniert nicht richtig.
Verfasst: Freitag 9. April 2010, 18:24
von jens
vielleicht besser mit .get() auf os.environ zugreifen
Warum die klammern bei if ?
Warum Exception Abfangen, wenn sieh eh nur ausgegeben werden?
Code kann man zusammen legen, schau dir mal an, worin die IFs sich wirklich unterscheiden

Verfasst: Freitag 9. April 2010, 21:24
von Ubuntuxer
Ich steh grad auf dem Schlauch, welchen Code kann ich sinnvoll zusammenlegen?

Verfasst: Freitag 9. April 2010, 21:38
von Whitie
Nur als Hinweis, bei mir ergibt
Code: Alles auswählen
In [2]: os.environ.get('DESKTOP_SESSION')
Out[2]: 'default'
Arch Linux, KDE 4.4.2, Python 2.6.5
Gruß Whitie
Verfasst: Samstag 10. April 2010, 00:42
von Dauerbaustelle
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python
import os
import dbus
DBUS_OBJECTS = {
'gnome' : {
'bus' : 'org.gnome.SessionManager',
'object' : '/org/gnome/SessionManager',
'interface' : 'org.gnome.SessionManager.RequestShutdown',
'bus_class' : dbus.SessionBus
},
'kde' : {
'bus' : 'org.kde.ksmserver',
'object' : '/KSMServer',
'interface' : 'org.kde.KSMServerInterface.logout',
'bus_class' : dbus.SessionBus
},
'default' : {
'bus' : 'org.freedesktop.Hal',
'object' : '/org/freedesktop/Hal/devices/computer',
'interface' : 'org.freedesktop.Hal.Device.SystemPowerManagement'
'bus_class' : dbus.SystemBus
}
}
def shutdown():
desktop_environment = os.environ['DESKTOP_SESSION']
environment_data = (DBUS_OBJECTS.get(desktop_environment)
or DBUS_OBJECTS['default'])
bus = environment_data['bus_class']()
remote_object = bus.get_object(environment_data['bus'], environment_data['object'])
remote_object.Shutdown(dbus_interface=environment_data['interface'])
if __name__ == "__main__":
shutdown()
Verfasst: Samstag 10. April 2010, 10:35
von lunar
Es ist völlig unnötig, hier die Umgebungsvariable zu prüfen. Es ist einfacher und zuverlässiger, der Reihe nach alle möglichen Dienste zu probieren, denn eine Sitzungsverwaltung läuft in der Regel nur, wenn eine vollwertige Desktop-Sitzung gestartet wurde.
Davon abgesehen ist DESKTOP_SESSION keine zuverlässige Quelle, weil diese Variable vom Display-Manager gesetzt wird. Wenn, dann sollte man auf die Existenz von "$KDE_FULL_SESSION=true" bzw. "$GNOME_DESKTOP_SESSION_ID" prüfen.
Im Übrigen funktioniert der "logout"-Aufruf für KDE so auch nicht, weil die Methode drei Parameter entgegen nimmt, welche bestimmen, wie das System heruntergefahren werden soll.
Verfasst: Sonntag 11. April 2010, 13:19
von snafu
Zum "sanften" Rebooten unter Gnome:
Code: Alles auswählen
dbus.SessionBus().get_object('org.gnome.SessionManager',
'/org/gnome/SessionManager').RequestReboot()
Analog dazu funktioniert bei mir RequestShutdown. Bei dem vorher gezeigten Code gab's nämlich ne DBusException.
Verfasst: Sonntag 11. April 2010, 13:23
von lunar
Das liegt daran, dass meine Vorredner mein Beitrag missverstanden haben. Die Methode heißt natürlich nicht immer "Shutdown"

Verfasst: Montag 12. April 2010, 13:59
von Ubuntuxer
Das liegt daran, dass meine Vorredner mein Beitrag missverstanden haben. Die Methode heißt natürlich nicht immer "Shutdown"
Ich hab mir jetzt mal die Dokumentation angesehen, das folgende Beispiel sollte funktionieren, auch wenn ich es nicht unter KDE getestet habe.
Das Zusammenfassen des doppelten Codes über das Dictionary finde ich nicht wirklich praktikabel und sinnvoll. Ich denke es erhöht nicht die lesbarkeit des Codes.
Code: Alles auswählen
#!/usr/bin/env python
import dbus
import os
def shutdown():
try:
bus = dbus.SessionBus()
remote_object = bus.get_object('org.gnome.SessionManager',
'/org/gnome/SessionManager')
remote_object.RequestShutdown()
except dbus.exceptions.DBusException:
pass
else:
return
try:
bus = dbus.SessionBus()
remote_object = bus.get_object('org.kde.ksmserver', '/KSMServer')
remote_object.logout(0, 0, 2, dbus_interface='org.kde.KSMServerInterface')
except dbus.exceptions.DBusException:
pass
else:
return
try:
bus = dbus.SystemBus()
remote_object = bus.get_object('org.freedesktop.Hal',
'/org/freedesktop/Hal/devices/computer')
remote_object.Shutdown(dbus_interface='org.freedesktop.Hal.Device.SystemPowerManagement')
except dbus.exceptions.DBusException:
print "Shutdown failed."
if __name__ == "__main__":
shutdown()
Verfasst: Montag 12. April 2010, 14:46
von lunar
Ich denke doch, dass es sinnvoll ist. Jede Wette, dass Du beim Verfassen dieses Beispiels die einzelnen Abschnitt kopiert, wieder eingefügt und anschließend geändert hast
