How to access session D-Bus from systemd user service?

强颜欢笑 提交于 2020-01-07 06:45:16

问题


I have user service running shell script, which is trying to access lockscreen state of my session like this:

# Test Unity screen-lock:
isLocked() {
    isLocked=$(gdbus call -e -d com.canonical.Unity -o /com/canonical/Unity/Session -m com.canonical.Unity.Session.IsLocked)
}

lock() {
  if [[ $isLocked == "(false,)" ]]; then                                                                                                     
        gnome-screensaver-command -l
  elif [[ $isLocked == "(true,)" ]]; then                                                                                                
        exit 1
  fi
exit 0
}

The problem is service “is a per-user process, and not per-session”, and I don't know how to access session dbus:

GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name com.canonical.Unity was not provided by any .service files

回答1:


I was facing this same problem, and my research turned up nothing. If someone can find a better way to query the lock status of Unity, I'd love to hear about it.

I recently learned about named pipes, and at the time I wondered what I might use such a thing for. This problem, it turns out, happens to be a perfect application.

Create the following script...

#!/bin/bash
# this script is meant to be called in two different ways.
# 1.    It can be called as a service by passing "service" as the first argument. In this 
#   mode, the script listens for requests for lock screen status. The script should be
#   run in this mode with startup applications on user logon.
# 2.    If this script is called without any arguments, it will call the service to request
#   the current lock screen status. Call this script in this manner from your user 
#   service.

# this will be the named pipe we'll use for requesting and receiving screen lock status
pipe="/tmp/lockscreen-status"

if [ "$1" == "service" ]; then
    # setup the named pipe
    rm "$pipe"
    mkfifo "$pipe"

    # start watching for requests
    while true
    do
        # watch the pipe for trigger events requesting lock screen status
        read request < "$pipe"

        # respond across the same pipe wit the current lock screen status
        gdbus call -e -d com.canonical.Unity -o /com/canonical/Unity/Session -m com.canonical.Unity.Session.IsLocked | grep -oP "(true)|(false)" > "$pipe"
    done
else
    # make sure the pipe exists
    if [ ! -e "$pipe" ]; then
        echo "This script must started in service mode before lock status can be queried."
        exit
    fi

    # send a request for screen lock status and read the response
    touch "$pipe"
    read status < "$pipe"

    [ "$status" == "" ] && status="This script must started in service mode before lock status can be queried."

    # print reponse to screen for use by calling application
    echo $status
fi

As noted in the comments, you need to call this script in two ways. When your user logs on, start this script in service mode. I use the "Startup Applications" program to call the script, but it doesn't really matter how it's called so long as its called by your user account on login. Then from within your user service, simply make a call to this script and it will return "true" if the screen is locked or "false" if the screen is unlocked.



来源:https://stackoverflow.com/questions/38623791/how-to-access-session-d-bus-from-systemd-user-service

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!