-   Linux - Desktop (
-   -   gnome-screensaver (or dbus ?) problem when activated via script (

Ranzen 10-29-2012 05:38 AM

gnome-screensaver (or dbus ?) problem when activated via script
Hi Folks

I have been using a small stolen script which locks the screen if i unplug a usb-key.
It used to work just fine. And i cannot remember when it stopped working.

I am using:
  • Fedora 17
  • with 3.6.x Kernel
  • gnome-screensaver 3.4.1

I used gnome-screensaver, but xscreensaver wont work either.

The screen locking itself works just fine if enter

gnome-screensaver-command --lock
or, for dbus

dbus-send --session --dest=org.gnome.ScreenSaver --type=method_call --print-reply /ScreenSaver org.gnome.ScreenSaver.Lock
directly on the shell.
I use the same command in my script.

The udev rule which actually starts the script does still work.
I can see in the log output that it tries to lock the screen.
So i start gnome-screensaver in foreground with debug and i see a dbus message, which is not there if i enter the "gnome-screensaver-command --lock" directly on the shell.


[listener_dbus_handle_system_message] gs-listener-dbus.c:854 (11:40:08):        obj_path=/org/freedesktop/login1/user/1000 interface=org.freedesktop.DBus.Properties method=PropertiesChanged destination=(null)
I am wondering what is required to pass this command from a script, running as root via udev.
So this would be my firtst question, requirements.

I spent some time with google and figured out that you need or may need these things:
  2. username of the user running the gnome session which you want to lock
  3. the DISPLAY
  4. content of .Xauthority (mit-magic-cookie ??? and what not)
It is said that one can find the DBUS_SESSION_BUS_ADDRESS in the environment of the gnome-screensaver process. so lets see:

grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(ps ax | grep gnome-screensaver | grep -v grep | awk {'print $1'})/environ


ok, for testing reasons i know who i am and hard-coded it into the script

The script will get the Display form /tmp/.X11-unix/. and since there is only one X and i am the only user at the localhost, i believe it if the result is "0"

There used to be a .Xauthority in my home. (i dont remember which century that was)
Now, there is apparently something like /var/run/gdm/auth-for-user-73sgPH/database
which might be the same, if you trust "xauth -v"

i think i have everything, maybe even too much.
But i cant firure out why the screensaver does not lock the screen anymore.

Do you guys have any idea what i can try ?
Or what is missing ?

Here is the script:
(It got a little messy, sorry)

# set static username if script is not able to get the correct name

getXuser() {

# ~/.Xauthority is manually created link from /var/run/gdm/auth-for-user-xxxx/database

        if [ x"$user" != x"" ]; then
                userhome=`getent passwd $user | cut -d: -f6`
                logger "DEBUG: $(date) userhome: '$userhome'"
                export XAUTHORITY=$userhome/.Xauthority
                export XAUTHORITY=""
        logger "DEBUG: $(date) Xauthority file: $XAUTHORITY"
        logger "DEBUG: $(date) user found: '$user'"

get_dbus_session() {
export "$(grep -z DBUS_SESSION_BUS_ADDRESS /proc/$(ps ax | grep gnome-screensaver | grep -v grep | awk {'print $1'})/environ)"

if [ "$1" = "lock" ] ; then

    for x in /tmp/.X11-unix/*; do
        displaynum=`echo $x | sed s#/tmp/.X11-unix/X##`
        logger "DEBUG: $(date) displaynum: '$displaynum'"
        if [ x"$XAUTHORITY" != x"" ]; then
            # extract current state
          export DISPLAY=":$displaynum"
        logger "DEBUG: $(date) Display:\"$DISPLAY\""

        userhome=`getent passwd $user | cut -d: -f6
        export XAUTHORITY=$userhome/.Xauthority
        logger "DEBUG: $(date) userhome: '$userhome'"
        logger "DEBUG: $(date) Xauthority file: $XAUTHORITY"
        logger "DEBUG: $(date) dbus session bus address: $DBUS_SESSION_BUS_ADDRESS"
    su $user -c "/usr/bin/gnome-screensaver-command --lock"
    su $user -c"dbus-send --session --dest=org.gnome.ScreenSaver --type=method_call --print-reply /ScreenSaver org.gnome.ScreenSaver.Lock"

elif [ "$1" = "unlock" ]; then

    for x in /tmp/.X11-unix/*; do
        displaynum=`echo $x | sed s#/tmp/.X11-unix/X##`
        if [ x"$XAUTHORITY" != x"" ]; then
            # extract current state
          export DISPLAY=":$displaynum"
        logger "DEBUG: $(date) Display: $DISPLAY"

    su $user -c "/usr/bin/gnome-screensaver-command -d"

fi ;
exit 0

PTrenholme 10-29-2012 07:33 PM

Not an answer to your question, but I believe that this idiom:

$(ps ax | grep gnome-screensaver | grep -v grep | awk {'print $1'})/environ)"}

could be simplified to

"/$(pgrep gnome-screensaver)/environ"

and the whole command simplified to
eval $(gawk 'BEGIN{RS="\0"}/DBUS_SESSION_BUS_ADDRESS/{print}' "/proc/$(pgrep gnome-screensaver)/environ")

(I prefer eval to export since, after all, a bash function is not executed in a child process and, even it it was so executed, all export would do - other that what eval does - is make the variable available to sub-processes of the process in which it was defined.

If I were writing it, I'd probably do something like this:

  local file look_for proc
  [ -z "${look_for}" ] && look_for="gnome_screensaver"
  proc="$(pgrep -u "${USER}" "${look_for}")"
  [ -z "${proc}" ] && echo "${look_for} is not currently running." >&2 && return 1
  [ ! -r "${file}" ] && echo "You do not have permission to read \"${file}.\"" >&2 && return 2
  eval $(gawk 'BEGIN{RS="\0"}/DBUS_SESSION_BUS_ADDRESS/{print}' "${file}")

I've always felt safer checking the assumptions made by a function before letting it run. (Hey, I wrote my first program as a sophomore in college in 1957, and not checking on an IBM system then could be have been very expensive.)

Oh, if you're concerned about the display value, part of the environment is a DISPLAY= value, which you can retrieve by changing the DBUS... string to DISPLAY. The return value is, usually, like ":0" since the full X-server name is "0:0" meaning "first connection:first display." If you've connected via ssh, the connection number may be higher, and if you're running several different window managers on different ttys the display number may be greater than 0.

Ranzen 10-30-2012 05:45 AM

eval versus export
Oh man, i completely forgot about pgrep.
Thanks for you help. I like the shorter/simplified command a lot.
Unfortunately pgrep does not find the gnome-screensaver process.

user@host:~$ps aux | grep gnome-screensaver
user    18828  0.0  0.1 391304  6192 pts/2    Sl  10:26  0:00 gnome-screensaver
user    19081  0.0  0.0 109400  832 pts/9    S+  10:41  0:00 grep --color=auto gnome-screensaver
user@host:~$pgrep gnome-screensaver

(i also copy pasted the name of the binary from the ps listing to pgrep, just to avoid typos, still no luck)
Then i tested "pgrep udev" and others, that worked.
I have no Idea, so i will have to stick with the long version.

The eval thing is somewhat strange.
There are already a lot of posts and questions about eval, so i try to keep it short.

I know that it is used to inderectly access a variable.
I dont know if this is what you wanted to say is the difference/advantage of eval.
But If i get you right you can use it to make a virable known to the parent??
But this should only be possible if the scripts output is a "export a=b" command and you eval the whole script, right?

PTrenholme 10-30-2012 06:18 PM

Hum. I don't use GNOME very much, but I just started a new instance on tty1, and, on my F17 system, the gnome-screensaver is reported as "gnome-screensav" (No "er" at the end of the string.)

I discovered this by doing a ps -e | grep screen, and after that showed the truncated name, I tried a pgrep "gnome-screensav" which returned the correct pid. (The command you used (ps ax | grep ...) did, as you noted, return the full name of the process invocation command.)

Ah! I just tried a pgrep -f gnome-screensaver and it worked! :D

Re the export question, if I understand the description of export correctly, there is no way to make a variable available to a parent process. Here's what man displays for export, with the key phrase in red:

export [-fn] [name[=word]] ...
export -p

The supplied names are marked for automatic export to the environment of subsequently executed commands. If the -f option is given, the names refer to functions. If no names are given, or if the -p option is supplied, a list of all names that are exported in this shell is printed. The -n option causes the export property to be removed from each name. If a variable name is followed by =word, the value of the variable is set to word. export returns an exit status of 0 unless an invalid option is encountered, one of the names is not a valid shell variable name, or -f is supplied with a name that is not a function.
Note that the parent of a command is not a subsequently executed command.

However, if the parent defines a variable, the child may change the value of that variable, and the changed value will be used by the parent.

To me it makes sense that anything defined in a child is discarded when the child terminates. If not, there would be a garbage collection problem, and other unintended consequences from a shared, common, shell namespace. (In fact, that's why most programming languages implement a "namespace" scope definition.)

Ranzen 03-13-2013 08:43 AM

never a touch a broken system
just to close this post:

some day some couple weeks ago i accidently started the script by plugging in the wrong usb stick,
and it worked. as it used to before. dont know what happend on the distro-side in between.
whatever it is, it made the script work again, since i did not changed the script since my last post.

All times are GMT -5. The time now is 12:37 AM.