Because D-Bus operates for the most part under the hood invisible to the user, means of monitoring D-Bus messages is important for both activation and debugging purposes. In this post I examine how to monitor and act on such messages. I assume that you are relatively familiar with D-Bus. If not, you should look at my previous posts on D-Bus to gain an understanding of the basic concepts.
Probably the most commonly used tool is the command line utility dbus-monitor which was written by Philip Blundell as part of the reference D-Bus implementation and which is standard on most D-Bus enabled platforms. It is a very powerful utility but unfortunately it’s man page is terse and fails to explain the most powerful feature of dbus-monitor i.e. watch expressions.
Suppose, for example, I want to monitor the creation, saving and deletion of Tomboy notes using D-Bus signals. To get the list of the supported signals I could introspect Tomboy using qdbus e.g.
$ qdbus org.gnome.Tomboy /org/gnome/Tomboy/RemoteControl | grep signal signal void org.gnome.Tomboy.RemoteControl.NoteAdded(QString uri) signal void org.gnome.Tomboy.RemoteControl.NoteDeleted(QString uri, QString title) signal void org.gnome.Tomboy.RemoteControl.NoteSaved(QString uri) $
or I could use dbus-monitor to look at the signals generated when Tomboy creates, saves and deletes a note.
$ dbus-monitor type=signal interface="org.gnome.Tomboy.RemoteControl" signal sender=org.freedesktop.DBus -> dest=:1.102 path=/org/freedesktop/DBus; interface=org.freedesktop.DBus; member=NameAcquired string ":1.102" signal sender=:1.63 -> dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteAdded string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc" signal sender=:1.63 -> dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteSaved string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc" signal sender=:1.63 -> dest=(null destination) path=/org/gnome/Tomboy/RemoteControl; interface=org.gnome.Tomboy.RemoteControl; member=NoteDeleted string "note://tomboy/0ae6b0b3-9394-44e9-ad4a-46726e68cebc" string "New Note 1" $
As you can see Tomboy issues three signals – NoteAdded when a note is added, NoteSaved when a note is saved, and NoteDeleted when a note is deleted. Interestingly, for some reason NoteDeleted provides both the uri and the title of the note whereas the other two signals only provide the uri.
Suppose I just want to to monitor when a Tomboy note is saved by a user. I can use a dbus-monitor watch expression for this purpose as shown in the following example.
dbus-monitor "type='signal',sender='org.gnome.Tomboy',interface='org.gnome.Tomboy.RemoteControl',path='/org/gnome/Tomboy/RemoteControl',member='NoteSaved'"
A watch expression is essentially a message filter. Note the syntax! Everything between the two double quotes is part of the watch expression.
Unfortunately the syntax of a watch expression is not documented in the dbus-monitor man page. However from looking at the source code for dbus-monitor, it appears that a watch expression consists of one or more name-value pairs, e.g. sender=’org.gnome.Tomboy’ separated by commas. The following are valid names: type, sender, destination, path, interface, member and error_name. The value of type must be one of the following: signal, method_call, method_return or error.
Probably the most powerful feature of dbus-monitor is the fact that you are not limited to using just one watch expression at a time. The following example simultaneously monitors all 3 Tomboy signals and uses awk to parse the output from dbus-monitor and display a meaningful message.
#!/bin/bash OJECT="'org.gnome.Tomboy'" IFACE="'org.gnome.Tomboy.RemoteControl'" DPATH="'/org/gnome/Tomboy/RemoteControl'" WATCH1="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteAdded'" WATCH2="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteSaved'" WATCH3="type='signal', sender=${OJECT}, interface=${IFACE}, path=${DPATH}, member='NoteDeleted'" dbus-monitor "${WATCH1}" "${WATCH2}" "${WATCH3}" | \ awk ' /member=NoteAdded/ { getline; print "Created note " substr($2,7) } /member=NoteSaved/ { getline; print "Added note " substr($2,7) } /member=NoteDeleted/ { getline; print "Deleted note " substr($2,7) } '
Here is the output generated when I clicked on the Tomboy icon to create a new note, waited for the automatic save and then selected the delete option to delete the note.
$ ./test Created note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824" Added note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824" Deleted note //tomboy/3da026dc-f6ee-4637-8a94-bec6e2844824"
Well that is all for this post. Enjoy!
P.S. All of the above examples were tested on Fedora 10. I have no idea whether they will work on other Linux distributions or versions of Fedora.