基本的なDbusエラー検出テクニック


数年の発展を経て、DbusはすでにLinuxデスクトップ環境で使われていたGNOME Bonobo、KDE DCOPに取って代わって、多くのアプリケーションで使われて、主流のIPCシステムになりました.ソフトウエアのオリジナルが成熟するにつれて、多くのプログラム言語がDbus APIsを支援し、Dbus daemonのfootprintも埋め込み式に受け入れられ、MeeGo、WebOSのような行動装置作業システムに採用されている.
Linux開発者は、介在需要のため、Dbusをテストしたり、使用したりする必要があります.ここではよく使われるいくつかのテクニックを共有します.Dbusは物件指向のAPIインタフェースを使用し,すべてのServicesのObject式はMethod,Signals,Propertiesの概念で外部アクセスに暴露され,Introspectable APIに合わせて第三者に容易に接続される.
最も一般的なツールの1つはdbus-sendであり、システムに登録されているすべてのSession BusのServicesをリストするように、命令列からDbus messagesをテストするために使用できます.
$ dbus-send --session --print-reply --reply-timeout=2000 \
--type=method_call --dest=org.freedesktop.DBus /org/freedesktop/DBus  \
org.freedesktop.DBus.ListActivatableNames

Servicesの名前が付いたら、サービス名でIntrospectionインタフェースで開いているAPIを検索できます.
$ dbus-send --session --print-reply --reply-timeout=2000 --type=method_call \
--dest=org.gnome.ScreenSaver / org.freedesktop.DBus.Introspectable.Introspect
method return sender=:1.7256 -> dest=:1.7286 reply_serial=2
 string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
 <interface name="org.freedesktop.DBus.Introspectable">
 <method name="Introspect">
 <arg name="data" direction="out" type="s"/>
 </method>
 </interface>
 <interface name="org.gnome.ScreenSaver">
 <method name="Lock">
 </method>
 <method name="Cycle">
 </method>
 <method name="SimulateUserActivity">
 </method>
 <method name="Inhibit">
 <arg name="application_name" direction="in" type="s"/>
 <arg name="reason" direction="in" type="s"/>
 <arg name="cookie" direction="out" type="u"/>
 </method>
 <method name="UnInhibit">
 <arg name="cookie" direction="in" type="u"/>
 </method>
 <method name="GetInhibitors">
 <arg name="list" direction="out" type="as"/>
 </method>
 <method name="Throttle">
 <arg name="application_name" direction="in" type="s"/>
 <arg name="reason" direction="in" type="s"/>
 <arg name="cookie" direction="out" type="u"/>
 </method>
 <method name="UnThrottle">
 <arg name="cookie" direction="in" type="u"/>
 </method>
 <method name="GetActive">
 <arg name="value" direction="out" type="b"/>
 </method>
 <method name="GetActiveTime">
 <arg name="seconds" direction="out" type="u"/>
 </method>
 <method name="SetActive">
 <arg name="value" direction="in" type="b"/>
 </method>
 <method name="ShowMessage">
 <arg name="summary" direction="in" type="s"/>
 <arg name="body" direction="in" type="s"/>
 <arg name="icon" direction="in" type="s"/>
 </method>
 <signal name="ActiveChanged">
 <arg name="new_value" type="b"/>
 </signal>
 </interface>
</node>
"
$ dbus-send --session --print-reply --reply-timeout=2000 \
--type=method_call --dest=org.gnome.Tomboy \
/org/gnome/Tomboy/RemoteControl org.freedesktop.DBus.Introspectable.Introspect
 string "<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<!-- NDesk.DBus 0.6.0 -->
<node>
 <interface name="org.freedesktop.DBus.Introspectable">
 <method name="Introspect">
 <arg name="data" direction="out" type="s" />
 </method>
 </interface>
 <interface name="org.gnome.Tomboy.RemoteControl">
 <method name="Version">
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="DisplayNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="HideNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="DisplayNoteWithSearch">
 <arg name="uri" direction="in" type="s" />
 <arg name="search" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="FindNote">
 <arg name="linked_title" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="FindStartHereNote">
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="CreateNote">
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="CreateNamedNote">
 <arg name="linked_title" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="CreateNamedNoteWithUri">
 <arg name="linked_title" direction="in" type="s" />
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="DeleteNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="DisplaySearch" />
 <method name="DisplaySearchWithText">
 <arg name="search_text" direction="in" type="s" />
 </method>
 <method name="NoteExists">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="ListAllNotes">
 <arg name="ret" direction="out" type="as" />
 </method>
 <method name="GetNoteContents">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="GetNoteTitle">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="GetNoteCreateDate">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="x" />
 </method>
 <method name="GetNoteChangeDate">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="x" />
 </method>
 <method name="GetNoteContentsXml">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="GetNoteCompleteXml">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="SetNoteContents">
 <arg name="uri" direction="in" type="s" />
 <arg name="text_contents" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="SetNoteContentsXml">
 <arg name="uri" direction="in" type="s" />
 <arg name="xml_contents" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="SetNoteCompleteXml">
 <arg name="uri" direction="in" type="s" />
 <arg name="xml_contents" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="GetTagsForNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="as" />
 </method>
 <method name="AddTagToNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="tag_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="RemoveTagFromNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="tag_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="GetAllNotesWithTag">
 <arg name="tag_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="as" />
 </method>
 <method name="GetNotebookForNote">
 <arg name="uri" direction="in" type="s" />
 <arg name="ret" direction="out" type="s" />
 </method>
 <method name="AddNoteToNotebook">
 <arg name="uri" direction="in" type="s" />
 <arg name="notebook_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="GetAllNotesInNotebook">
 <arg name="notebook_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="as" />
 </method>
 <method name="AddNotebook">
 <arg name="notebook_name" direction="in" type="s" />
 <arg name="ret" direction="out" type="b" />
 </method>
 <method name="SearchNotes">
 <arg name="query" direction="in" type="s" />
 <arg name="case_sensitive" direction="in" type="b" />
 <arg name="ret" direction="out" type="as" />
 </method>
 <signal name="NoteDeleted">
 <arg name="uri" direction="out" type="s" />
 <arg name="title" direction="out" type="s" />
 </signal>
 <signal name="NoteAdded">
 <arg name="uri" direction="out" type="s" />
 </signal>
 <signal name="NoteSaved">
 <arg name="uri" direction="out" type="s" />
 </signal>
 </interface>
</node>"

ただし、object nameはサービス定義によって異なり、最初のクエリは/から調べることができ、Dbusはサブパスに応答します.
APIインタフェースがあれば、dbus-sendでこれらのServicesにコマンドを直接送ることができます.以下にスクリーン保護プログラムを起動します.
dbus-send --session --dest=org.gnome.ScreenSaver \
--type=method_call --print-reply --reply-timeout=20000 \
/ org.gnome.ScreenSaver.SetActive boolean:true

パラメータのフォーマットは、Dbus仕様のType Signaturesを参照してください.
Desktop環境でDbus APIsを検索したい場合は、比較的簡単なツールはd-feetを使用します.これはPython/GTKが書いたツールで、マウスが点在するだけで様々なAPIを検索したり、命令メッセージを送ったりすることができます.(以下の画像はd-feetから)
基本的なテストツールを知った後、テスト期間中にメッセージの伝達と反応が正しいかどうかを観測する必要がある場合、dbus-monitorを利用することができます.システム内のすべてのDbus messagesを監視し、ソフトウェアが正常に動作しているかどうかを確認するのに便利です.
安全性を考慮すると、dbus-monitorは、各Loginセッションで使用者が開いているソフトウェアを意味するSession Busのメッセージのみを監視するように設定されています.System Busでは、Network Managerなどのプリセットはアクセスできません.これは、パスワードなどの情報を悪用しないようにするためです.
手動で権限を開く必要があります.設定方法は、以下の設定ファイルを変更し、eavesdrop policyを開き、Dbus daemonを再起動することです.このようにしてこそ、関連通信を盗聴することができる.
cat > /etc/dbus-1/system-local.conf
<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
 "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
<busconfig>
  <policy context="default">
    <!-- All messages may be received by default -->
    <allow receive_requested_reply="false" receive_type="method_call" eavesdrop="true"/>
    <allow receive_requested_reply="false" receive_type="method_return" eavesdrop="true"/>
    <allow receive_requested_reply="false" receive_type="error" eavesdrop="true"/>
    <allow receive_requested_reply="false" receive_type="signal" eavesdrop="true"/>
    <allow eavesdrop="true"/>
  </policy>
  <policy user="root">
      <allow send_destination="*" eavesdrop="true"/>
      <allow receive_sender="*" eavesdrop="true"/>
  </policy>
</busconfig>

詳しくはご参考ください
D-Bus Specification
MeeGo D-Bus/Overview
Scripting D-Bus
ソース:http://people.debian.org.tw/~chihchun/2011/03/08/test-and-debug-dbus/