D-Bus-Methodenaufruf am Beispiel von Suspend

Per D-Bus kann man Systemd mitteilen, dass es zum Beispiel den Rechner schlafenlegen soll. Den Weg dorthin will ich hier kurz skizzieren, da mir dies beim ersten Mal nicht so leicht fiel und ich zur Zeit häufiger mit D-Bus zu tun habe.

Die Methode finden

Mit Systemd kommt das Programm busctl, über das auf der Kommandozeile mit D-Bus interagieren kann. Mit busctl list kann man sich die Liste der laufenden Dienste abrufen:

NAME                                   PID PROCESS         USER             CONNECTION    UNIT                      SESSION    DESCRIPTION        
:1.0                                     1 systemd         root             :1.0          init.scope                -          -                  
:1.1                                   695 avahi-daemon    avahi            :1.1          avahi-daemon.service      -          -                  
:1.10                                  913 polkitd         root             :1.10         polkit.service            -          -                  
:1.107                               26881 Xorg            joerg            :1.107        session-13.scope          13         -                  
:1.108                               26889 ck-launch-sessi joerg            :1.108        session-13.scope          13         -                  
:1.126                                2882 systemd-network systemd-network  :1.126        systemd-networkd.service  -          -                  
:1.127                                2885 systemd-resolve systemd-resolve  :1.127        systemd-resolved.service  -          -                  
:1.2                                   697 systemd-logind  root             :1.2          systemd-logind.service    -          -                  
:1.202                                3395 busctl          joerg            :1.202        session-13.scope          13         -                  
org.bluez                                - -               -                (activatable) -                         -         
org.freedesktop.Avahi                  695 avahi-daemon    avahi            :1.1          avahi-daemon.service      -          -                  
org.freedesktop.ColorManager             - -               -                (activatable) -                         -         
org.freedesktop.ConsoleKit             847 console-kit-dae root             :1.8          console-kit-daemon.ser…ce -          -                  
org.freedesktop.DBus                   700 dbus-daemon     messagebus       org.freedesktop.DBus dbus.service              -          -                  
org.freedesktop.PolicyKit1             913 polkitd         root             :1.10         polkit.service            -          -                  
org.freedesktop.RealtimeKit1           704 rtkit-daemon    root             :1.3          rtkit-daemon.service      -          -                  
org.freedesktop.UDisks2                  - -               -                (activatable) -                         -         
org.freedesktop.hostname1                - -               -                (activatable) -                         -         
org.freedesktop.locale1                  - -               -                (activatable) -                         -         
org.freedesktop.login1                 697 systemd-logind  root             :1.2          systemd-logind.service    -          -                  
org.freedesktop.network1              2882 systemd-network systemd-network  :1.126        systemd-networkd.service  -          -                  
org.freedesktop.resolve1              2885 systemd-resolve systemd-resolve  :1.127        systemd-resolved.service  -          -                  
org.freedesktop.systemd1                 1 systemd         root             :1.0          init.scope                -          -                  
org.freedesktop.timedate1                - -               -                (activatable) -                         -

Hier ist der Dienst login1 verzeichnet, der das System in den Schlaf schicken kann. Mit busctl tree org.freedesktop.login1 kann man sich die Knoten anzeigen lassen, über die man mit dem Dienst kommunizieren kann:

└─/org
  └─/org/freedesktop
    └─/org/freedesktop/login1
      ├─/org/freedesktop/login1/seat
      │ ├─/org/freedesktop/login1/seat/seat0
      │ └─/org/freedesktop/login1/seat/self
      ├─/org/freedesktop/login1/session
      │ ├─/org/freedesktop/login1/session/_313
      │ ├─/org/freedesktop/login1/session/_317
      │ └─/org/freedesktop/login1/session/self
      └─/org/freedesktop/login1/user
        ├─/org/freedesktop/login1/user/_0
        ├─/org/freedesktop/login1/user/_1000
        └─/org/freedesktop/login1/user/self

Aufgrund unendlicher Weisheit 😉 (oder man rät halt rum) erkennt man, dass der Knoten /org/freedesktop/login1 der richtige ist. Von diesem kann man mit busctl introspect org.freedesktop.login1 /org/freedesktop/login1 die Eigenschaften abrufen:

NAME                                TYPE      SIGNATURE          RESULT/VALUE     FLAGS
org.freedesktop.DBus.Introspectable interface -                  -                -
.Introspect                         method    -                  s                -
org.freedesktop.DBus.Peer           interface -                  -                -
.GetMachineId                       method    -                  s                -
.Ping                               method    -                  -                -
org.freedesktop.DBus.Properties     interface -                  -                -
.Get                                method    ss                 v                -
.GetAll                             method    s                  a{sv}            -
.Set                                method    ssv                -                -
.PropertiesChanged                  signal    sa{sv}as           -                -
org.freedesktop.login1.Manager      interface -                  -                -
.ActivateSession                    method    s                  -                -
.ActivateSessionOnSeat              method    ss                 -                -
.AttachDevice                       method    ssb                -                -
.CanHibernate                       method    -                  s                -
.CanHybridSleep                     method    -                  s                -
.CanPowerOff                        method    -                  s                -
.CanReboot                          method    -                  s                -
.CanRebootToFirmwareSetup           method    -                  s                -
.CanSuspend                         method    -                  s                -
.CancelScheduledShutdown            method    -                  b                -
.CreateSession                      method    uusssssussbssa(sv) soshusub         -
.FlushDevices                       method    b                  -                -
.GetSeat                            method    s                  o                -
.GetSession                         method    s                  o                -
.GetSessionByPID                    method    u                  o                -
.GetUser                            method    u                  o                -
.GetUserByPID                       method    u                  o                -
.Hibernate                          method    b                  -                -
.HybridSleep                        method    b                  -                -
.Inhibit                            method    ssss               h                -
.KillSession                        method    ssi                -                -
.KillUser                           method    ui                 -                -
.ListInhibitors                     method    -                  a(ssssuu)        -
.ListSeats                          method    -                  a(so)            -
.ListSessions                       method    -                  a(susso)         -
.ListUsers                          method    -                  a(uso)           -
.LockSession                        method    s                  -                -
.LockSessions                       method    -                  -                -
.PowerOff                           method    b                  -                -
.Reboot                             method    b                  -                -
.ReleaseSession                     method    s                  -                -
.ScheduleShutdown                   method    st                 -                -
.SetRebootToFirmwareSetup           method    b                  -                -
.SetUserLinger                      method    ubb                -                -
.SetWallMessage                     method    sb                 -                -
.Suspend                            method    b                  -                -
.TerminateSeat                      method    s                  -                -
.TerminateSession                   method    s                  -                -
.TerminateUser                      method    u                  -                -
.UnlockSession                      method    s                  -                -
.UnlockSessions                     method    -                  -                -
.BlockInhibited                     property  s                  ""               emits-change
.DelayInhibited                     property  s                  "sleep"          emits-change
.Docked                             property  b                  false            -
.EnableWallMessages                 property  b                  true             writable
.HandleHibernateKey                 property  s                  "hibernate"      const
.HandleLidSwitch                    property  s                  "suspend"        const
.HandleLidSwitchDocked              property  s                  "ignore"         const
.HandlePowerKey                     property  s                  "poweroff"       const
.HandleSuspendKey                   property  s                  "suspend"        const
.HoldoffTimeoutUSec                 property  t                  30000000         const
.IdleAction                         property  s                  "ignore"         const
.IdleActionUSec                     property  t                  1800000000       const
.IdleHint                           property  b                  true             emits-change
.IdleSinceHint                      property  t                  1493720617977543 emits-change
.IdleSinceHintMonotonic             property  t                  234145519029     emits-change
.InhibitDelayMaxUSec                property  t                  5000000          const
.InhibitorsMax                      property  t                  8192             const
.KillExcludeUsers                   property  as                 0                const
.KillOnlyUsers                      property  as                 0                const
.KillUserProcesses                  property  b                  false            const
.NAutoVTs                           property  u                  6                const
.NCurrentInhibitors                 property  t                  1                -
.NCurrentSessions                   property  t                  2                -
.PreparingForShutdown               property  b                  false            -
.PreparingForSleep                  property  b                  false            -
.RebootToFirmwareSetup              property  b                  false            const
.RemoveIPC                          property  b                  true             const
.RuntimeDirectorySize               property  t                  1671409664       const
.ScheduledShutdown                  property  (st)               "" 0             -
.SessionsMax                        property  t                  8192             const
.UserTasksMax                       property  t                  10813            const
.WallMessage                        property  s                  ""               writable
.PrepareForShutdown                 signal    b                  -                -
.PrepareForSleep                    signal    b                  -                -
.SeatNew                            signal    so                 -                -
.SeatRemoved                        signal    so                 -                -
.SessionNew                         signal    so                 -                -
.SessionRemoved                     signal    so                 -                -
.UserNew                            signal    uo                 -                -
.UserRemoved                        signal    uo                 -                -

Die Methode, um das System in den Schlaf zu schicken, ist Suspend. Irgendwo in den unendlichen Weiten der Systemd-Dokumentation wird das bestimmt vermerkt sein – oder man rät wieder. Mit all diesen Informationen kann man jetzt die Methode mittels busctl call <DIENST> <KNOTEN> <SCHNITTSTELLE> <METHODE> <TYP-PARAM-1> <PARAM-1> <TYP-PARAM-2> <PARAM-2> … aufrufen. Auf der Ausgabe von introspect kann man noch die Schnittstelle, die die Methode bereitstellt, und die Parameter(-typen) der Methode ablesen:

NAME                                TYPE      SIGNATURE          RESULT/VALUE     FLAGS

org.freedesktop.login1.Manager      interface -                  -                -
…
.Suspend                            method    b                  -                -

Der Parametertyp b steht für boolean. Somit ergibt sich der Aufruf:

busctl call org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager Suspend b true

Den Aufruf bzw. das Versenden der Nachricht, wie es in der D-Bus-Sprache bezeichnet wird, kann man auch mit dem Programm dbus-send durchführen. Hierbei muss man aber angeben, dass es ein System-Dienst ist, mit dem man kommunizieren will, da busctl immer von System-Diensten ausgeht und für Benutzer-Dienste einen Parameter erfordert.

% dbus-send --system --print-reply --dest=org.freedesktop.login1 /org/freedesktop/login1 org.freedesktop.login1.Manager.Suspend boolean:true
method return time=1493727858.922660 sender=:1.2 -> destination=:1.212 serial=1292 reply_serial=2