Desktop-Agnostic Detection of DBus Sessions

Linux Logo Here’s a little gem I came up after a few hours of brain-wracking.

The goal involves the scripts I use to have my computers communicate with the file server about which updates they need, and to nag the user (me) about available updates.  After some time, I realized that a user-based approach wasn’t ideal.  Besides the fact that each user needs a tab entry in cron on each computer, and that you can be logged in at multiple computers at one time (which really isn’t a good idea if /home is being shared over NFS), aren’t updates a system thing anyway?  Why depend on a user being logged in, when part of the convenience is having your updates already downloaded for you?

The problem then becomes, “How do I notify any active users on the system about available updates?”  I solved this initially by using a script I could call upon starting my desktop environment that would dump the DBUS_SESSION_BUS_ADDRESS variable into a file in my home directory.  But now I needed a way for the root user to do it.  I saw code snippets where people searched the names of common desktop binaries, but I wanted a desktop-agnostic solution that would work no matter which desktop you were using or what your chosen desktop does in the future with the names of its binaries.

Well, Linux has part of this problem solved already.  In /proc you will find a bunch of numbered directories.  These numbers relate to Process IDs, and Linux keeps track of the environment variables that each process is running with.  Additionally, these environment variables are in a simple text file called environ.  If you wanted to lump the whole thing together, it takes one command.

cat /proc/*/environ

Of course, that’s going to be a lot of text to wade through.  That’s where grep comes in.

cat /proc/*/environ | grep -z DBUS_SESSION_BUS_ADDRESS

Now we only have occurrances of DBUS_SESSION_BUS_ADDRESS, but we want unique occurances.

cat /proc/*/environ | grep -z DBUS_SESSION_BUS_ADDRESS | sort -uz

Now we all the uniqe DBUS_SESSION_BUS_ADDRESS values in use on this system.  But we want to get rid of the actual variable name.  We can use cut, but cut doesn’t handle null-terminated lines. We can use the tr (translate) command to convert the nulls into newlines so that we can further process the output with cut.

cat /proc/*/environ | grep -z DBUS_SESSION_BUS_ADDRESS | sort -uz | tr '' '\n' | cut -d= -f2-

Isn’t this hammering the system?  In my not-so-scientific study, the code is wading through about 64K of data and takes 26ms tops on an AMD AM2 2GHz dual-core processor, with the bulk of the time spent (~17ms) on cat and grep. Using ps -Nd to only get Session Leaders took just as much or more time searching for results to pass to the cat command than just using the brute-force lump-it-all-together approach.  Any kind of looping made the operation take ten times as long.