いますぐ実践! Linuxシステム管理

[バックナンバーのトップへ] [Linux システム管理のトップへ]


いますぐ実践! Linux システム管理 / Vol.175 / 読者数:1483名

こんばんは、うすだです。

この間、マシンをリブートしてGNOMEでログインしなおしたところ、 Shift キーが効かなくなってしまいました。

SSHでログインする際に、パスワードを何度入力しても受け付けられないので、 おかしいなーと思っていたのですが、大文字や記号を入力できないことで、 Shift キーの不全に気づいた次第です。

それにしても、Shift キーが使えないと、ものすごく不便です。
普段、存在するのが当たり前だと思っていることが、 実はありがたいことなのだということを、ひしひしと感じました。
(あと、お腹をこわしたときにも、健康の大切さに気づかされますよね。)

あ、それで、結局なにが原因だったかといいますと、 grandr という画面設定のアプリケーションで、 ホットキーを有功にしていたためでした。
(ホットキーを無効にしたら元に戻りましたが、 なぜ Shift キーそのものの機能が奪われてしまったのかは、未だ不明です。)

これからは、自分がなにか設定などを行ったら、 メモらないといけないと思いました。
いえ、本当は、メモるのが面倒なので、GNOMEに、 シェルのヒストリ機能的なものがあればいいのになあと思っています。ただ、 設定の変更までも記録するのは、ちょっと難しいかもしれませんね。

それでは、いつもよりも Shift キーの存在のありがたさを感じながら、 今週もはりきってまいります。

今回のお題 - D-Bus の存在を感じてみる

前回〜前々回と、NetworkManager の使い方などをご紹介しました。

Vol.173 - NetworkManager を活用する
http://www.usupi.org/sysad/173.html
Vol.174 - NetworkManager をもう少し活用してみる
http://www.usupi.org/sysad/174.html

NetworkManagerアプレットや cnetworkmanagerというコマンドで、 ネットワークの設定変更などを行いました。ですが、 これらが直接ネットワークの設定を行っているわけではありません。

実は、NetworkManager というデーモンが動作しており、 NetworkManagerデーモンさんにお願いして、 設定などを行ってもらっているのです。
そして、そのお願いは、D-Bus と呼ばれるプロセス間通信の機構を使って行っています。

恥ずかしながら、わたくしは D-Bus の名前くらいしか知りませんでしたので、 これをよい機会だと思い、ちょこっと調べてみました。

というわけで今回は、D-Bus の概要と、 D-Bus を使ったやりとりを比較的簡単に試す方法を、ご紹介したいと思います。

D-Bus とは?

D-Bus とは、アプリケーション間で通信を行う「プロセス間通信」の機構のひとつです。

HAL や NetworkManager などのデーモンとの通信で用いられる他、 KDE や GNOME といったデスクトップ環境でも使われています。

Software/dbus
http://www.freedesktop.org/wiki/Software/dbus

D-Bus Specification
http://dbus.freedesktop.org/doc/dbus-specification.html

D-Bus Specification (上記の日本語訳)
http://www1.ocn.ne.jp/~s_step/html/ja/dbus/dbus-specification.html

不正確なのを承知で、D-Bus について超簡単に駆け足でご説明しますと、 以下のようになる…と思います。

  • アプリケーション間は、基本的には 1対1 で通信します。
  • 通信の際には、「メッセージ」をやりとりします。
  • メッセージには、 「メソッド(関数)」と 「シグナル」があります。
  • メソッドは、 相手に何らかの処理をしてもらうためのもので、通常は、処理した結果が戻ってきます。
  • シグナルは、相手に何かを通知するためのものです。
  • 通信は、バスを介して行われます。
    バスには、 「システムバス」と 「セッションバス」があります。
  • システムバスは、システムとのやりとりで使われます。
  • セッションバスは、主にデスクトップ環境で使われます。
  • バス名で、通信相手を特定します。
    org.freedesktop.NetworkManagerのような、 みんな知っている有名(?)な名前もあれば、使用中のみ有効な : で始まる名前もあります。
  • 通信相手は、いくつかの「オブジェクト」を持っています。
    たとえば、NetworkManager は、eth0 などのデバイスや、 そのデバイスに対する接続の情報を持っていますが、 デバイスも接続もオブジェクトとして扱われます。
  • オブジェクトは、 「オブジェクトパス」で指定します。
    たとえば、/org/freedesktop/NetworkManager/Devices/0 のように表します。(ちなみにこれは NetworkManager のデバイスです。)
  • メッセージオブジェクトに対して送信されます。
    オブジェクトが受け付けるメッセージは、 「インターフェース」で定義されています。

他にも、認証なども行えるようなのですが、 今のところはわたしの理解の範疇を越えていますので、ご紹介は控えさせていただきます。

※ 以降では、メッセージを緑バスを赤オブジェクトを紫インターフェースを黄 で表してみました。かえってわかりにくかったら申し訳ありません。

では試しましょう…の前に

D-Bus の概要を箇条書きでご説明してみましたが、具体的な例がないと、 さっぱりわからないですよね。

以降では、dbus-send というコマンドを使って、 D-Bus による通信を試みていきます。
その dbus-send コマンドの書式は、以下の通りです。

  dbus-send [--system | --session] [--dest=NAME] [--type=TYPE] \
      [--print-reply] OBJECT_PATH MESSAGE_NAME [ARGS...]

[] で囲んだ部分は、省略可能です。
また、大文字で表記したところには、具体的な名前を指定します。

まず、使用するバスを、 --system--sessionで指定します。
お察しの通り、前者がシステムバス、 後者がセッションバスですが、 省略すると --sessionを指定したことになります。

次に、--dest オプションで、 通信相手であるバス名を指定します。 そして、--type オプションで、 メッセージの種別を指定します。
メソッドの場合は method_callシグナルの場合はsignalを指定しますが、 省略するとsignalを指定したことになります。 メソッドを指定したとき、 --print-reply オプションを指定すると、相手からの応答を出力します。

OBJECT_PATHには、 メッセージを送りつける対象となるオブジェクトを、 オブジェクトパスで指定します。

MESSAGE_NAMEには、インターフェースで定義されたメッセージ(メソッドやシグナル)を指定します。 もし、使用するメッセージに引数がある場合は、 ARGS...で指定します。

今度こそ試します

…あ、dbus-send コマンドの大雑把な説明だけで終わってしまいました。
今度こそ、実際に試してみたいと思います。

ここでは、バス名org.freedesktop.DBusという、 D-Bus の大ボス的な相手と通信してみたいと思います。
(突然名前が出てきましたが、そういうのがいると思ってください。)

オブジェクトは、バス名の . を / に置き換えたものが、 わたしの経験上では大抵存在する思われますので、 ここでは /org/freedesktop/DBus に対して送信をしてみます。

そしてインターフェースですが、 org.freedesktop.DBus.IntrospectableIntrospectというメソッドを指定してみます。
これは、D-Bus の仕様にある標準インターフェースのひとつで、 指定したオブジェクトインターフェースを XML 形式で返してくれるものです。
引数が要りませんし、そのオブジェクトがどんなインターフェースに対応しているかがわかりますので、 とても便利なメソッドだと思います。

あと、バスは、どちらでも返事をくださいますが、 ひとまずシステムバス(--system)を使用してみたいと思います。

というわけで、上記を踏まえた実行例が、以下のようになります。

  $ dbus-send --system --dest=org.freedesktop.DBus \
  --type=method_call --print-reply /org/freedesktop/DBus \
  org.freedesktop.DBus.Introspectable.Introspect
  method return sender=org.freedesktop.DBus -> dest=:1.390 \
  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.freedesktop.DBus">
  ...
     <method name="ListNames">
        <arg direction="out" type="as"/>
      </method>
  ...
    </interface>
  </node>
  "

4行目の method return 云々以降が、dbus-send コマンドの出力です。
6行め以降が、Introspect メソッドのお返事です。
10行目には、org.freedesktop.DBus.Introspectable インターフェースが出てきています。 Introspectというメソッドだけを持ち、 data という名の出力の引数だけを持つことがわかります。

そして、15行目には、org.freedesktop.DBus というインターフェースがあり、 その中にListNamesというメソッドがあることがわかります。
今度は、これを呼び出してみましょう。
先ほどとは、通信相手オブジェクトも同じで、 メッセージだけが異なりますので、 以下のように実行することになります。

  $ dbus-send --system --dest=org.freedesktop.DBus \
  --type=method_call--print-reply /org/freedesktop/DBus \
  org.freedesktop.DBus.ListNames
  method return sender=org.freedesktop.DBus -> dest=:1.392 \
  reply_serial=2
     array [
        string "org.freedesktop.DBus"
        string ":1.106"
        string ":1.7"
  ...
        string "org.gnome.DisplayManager"
        string "org.freedesktop.Avahi"
        string "org.freedesktop.ConsoleKit"
        string "org.freedesktop.Hal"
  ...

このメソッドは、存在するバス名の一覧を配列で返します。
これにより、さらに通信できそうな相手が見つかりましたので、 芋づる式にたどっていけば、いろいろわかるのではないかと思います。

それでは、試しにorg.freedesktop.Halさんのインターフェースを確認してみましょう。

  $ dbus-send --system --dest=org.freedesktop.Hal \
  --type=method_call --print-reply /org/freedesktop/Hal \
  org.freedesktop.DBus.Introspectable.Introspect
  ...
  <node>
    <interface name="org.freedesktop.DBus.Introspectable">
      <method name="Introspect">
        <arg name="data" direction="out" type="s"/>
      </method>
    </interface>
    <node name="Manager"/>
    <node name="devices"/>
  </node>
  ...

/org/freedesktop/Halの下に、 Managerdevicesというオブジェクトがあるようです。
/org/freedesktop/Hal/Managerをたどってみましょう。

  $ dbus-send --system --dest=org.freedesktop.Hal \
  --type=method_call --print-reply /org/freedesktop/Hal/Manager \
  org.freedesktop.DBus.Introspectable.Introspect
  ...
    <interface name="org.freedesktop.Hal.Manager">
      <method name="GetAllDevices">
        <arg name="devices" direction="out" type="as"/>
      </method>
  ...
      <method name="DeviceExists">
        <arg name="does_it_exist" direction="out" type="b"/>
        <arg name="udi" direction="in" type="s"/>
      </method>
  ...
      <method name="Remove">
        <arg name="udi" direction="in" type="s"/>
      </method>
  ...

GetAllDevicesで、デバイス一覧を得られそうです。

  $ dbus-send --system --dest=org.freedesktop.Hal \
  --type=method_call --print-reply /org/freedesktop/Hal/Manager \
  org.freedesktop.Hal.Manager.GetAllDevices
  method return sender=:1.2 -> dest=:1.425 reply_serial=2
     array [
      string "/org/freedesktop/Hal/devices/net_00_01_02_03_04_05"
      string "/org/freedesktop/Hal/devices/volume_part4_size_1024"
      string "/org/freedesktop/Hal/devices/computer"
  ...

得られました。(とはいえ、lshal -s の方が簡単ですが…。)

DeviceExistsで、 デバイスの有無がわかりそうです。
これには、文字列(type="s")の引数(name="udi" direction="in")が必要ですので、 指定してみます。

  $ dbus-send --system --dest=org.freedesktop.Hal \
  --type=method_call --print-reply /org/freedesktop/Hal/Manager \
  org.freedesktop.Hal.Manager.DeviceExists \
  string:"/org/freedesktop/Hal/devices/computer"
  method return sender=:1.2 -> dest=:1.426 reply_serial=2
     boolean true
  $ dbus-send --system --dest=org.freedesktop.Hal \
  --type=method_call --print-reply /org/freedesktop/Hal/Manager \
  org.freedesktop.Hal.Manager.DeviceExists \
  string:"/ari/enai/device/name"
  method return sender=:1.2 -> dest=:1.427 reply_serial=2
     boolean false

実在するデバイスを指定すると true が、 そうでないと false がきちんと返ってきました。

あと、恐ろしいですが、Removeを試してみましょう。
ほんとにRemoveされるといけませんので、 デタラメなモノで試します。

  $ dbus-send --system --dest=org.freedesktop.Hal \
  --type=method_call --print-reply /org/freedesktop/Hal/Manager \
  org.freedesktop.Hal.Manager.Remove string:"usouso"
  Error org.freedesktop.Hal.PermissionDenied: Permission denied: \
  Remove: not privileged

…ああ、ちゃんと権限がないとおっしゃっていただけました。(ふぅ)

おわりに

以上、D-Bus の概要と、試しに通信する方法を、ご紹介しました。

普通にシステム管理を行うだけなら、 別に D-Bus のことを知らなくても特に支障はないと思います。
ですが、大雑把でも知っておきますと、 なにかトラブルが発生したときに想像しやすくなりますし、 D-Bus を知らないひとにうんちくをたれることもできます。

というわけで、いろいろたどりながら試してみてくださいませ。

あ、あと、NetworkManager とのやりとりまでたどり着けませんでした。
ものすごく評判が悪かった! ということがなければ、次回にご紹介したいと思います。

宿題の答え

前回の宿題は、

  NetworkManager では一般ユーザの権限でネットワークの設定ができて
  しまいます。なぜそれが可能なのか、考えてみましょう。

でした。

本題の冒頭で答えを書いてしまいましたが、 NetworkManagerデーモンさんに D-Bus 経由でお願いし、 NetworkManagerデーモンさんが設定するためです。

ですので、NetworkManagerアプレットなどが一般ユーザの権限で動作していて、 ネットワークの設定などを行う権限を持っていなくても、 D-Bus で通信さえできれば、 root の権限で動作する NetworkManagerデーモンさんに行ってもらえるというわけですね。

ということはつまり、dbus-sendコマンドを使って、 直接 NetworkManagerデーモンさんとやりとりすることもできます。
たとえば、以下のように実行しますと、接続を変更できます。
(下記の、接続 /org/freedesktop/NetworkManagerSettings/4 とデバイス /org/freedesktop/NetworkManager/Devices/0オブジェクトパスは、 ご使用の環境によって異なります。)

  $ dbus-send --system --dest=org.freedesktop.NetworkManager \
  --print-reply --type=method_call /org/freedesktop/NetworkManager \
  org.freedesktop.NetworkManager.ActivateConnection \
  string:"org.freedesktop.NetworkManagerSystemSettings" \
  objpath:"/org/freedesktop/NetworkManagerSettings/4" \
  objpath:"/org/freedesktop/NetworkManager/Devices/0" objpath:"/"

ちなみに上記は、デスクトップを使用しているユーザに限られる、 というわけでもなく、だれでも実行できました。(いいんでしょうかね…。)

今回の宿題

今回の宿題は、

  org.gnome.ScreenSaver といろいろ通信してみましょう。

です。

本題でご紹介しましたように、インターフェースを確認して、 スクリーンセーバを有効にしたり、設定を確認したりしてみてください。

あとがき

わたくしごとで恐縮ですが、 3月8日に発売(明日…あ、もう今日ですね)の日経Linuxの4月号に、 X Window System に関する記事を書かせていただきました。

オープンソース/Linux : ITpro
http://itpro.nikkeibp.co.jp/linux/index.html

雑誌の文章を書いた経験がありませんでしたので、不慣れさ満開で書いたのですが、 編集の方の魔法によって、初稿とは似ても似つかない、 きちんとした文章に仕上がった…と思います。

さらにあつかましく、タイトルの絵まで描かせていただいております。
ラフな絵をお送りしたら、ありがたいことに許可をいただきましたので、 気合いを入れて描きました。(調子に乗って、中の説明の図までも…。)

そんなところも含めて、書店で立読みなどしていただけますと幸いです。
(あわよくば購入していただけますと、もっと幸いです。)

連載ということになっていますので、評判が悪いとか、 初稿がひどすぎるということがなければ、ある程度続くと思います。
原稿の締切りのため、月末が火の車になりますが、 滅多に得られない経験だと思いますので、 少しでも面白いと思っていただける内容になるよう、 精進しながら書いていきます。

というわけで、今後ともよろしくお願いします。
(…とここまで書いておいて、いきなり打ちきられたらどうしよう? と、 早くも心配している小心者です。)

 

今回も、ここまで読んでいただき、誠にありがとうございました。
次回は、3月21日(日) の未明にお会いしましょう!

 

「いますぐ実践! Linux システム管理」の解除は、以下からできます。
http://www.usupi.org/sysad/ (まぐまぐ ID:149633)

バックナンバーは、こちらにほぼ全部そろっています。
http://www.usupi.org/sysad/backno.html

「栗日記」- 栗の木のオーナーになりました。現物はまだ見てませんが。
http://www.usupi.org/kuri/ (まぐまぐ ID:126454)
http://usupi.seesaa.net/ (栗日記ブログ)
http://usupi.org/k/ (モバイル栗日記)


[バックナンバーのトップへ] [Linux システム管理のトップへ]

トップ

バックナンバー
    [日付順] [目的別]

プロフィール

▼ リンク

独学Linux
Linuxデスクトップ環境に関する情報が満載です。 メルマガもありますよ。
Server World
CentOS 6をサーバとしたときの設定例が、これでもかというくらいたくさん載っています。 CentOS以外のディストリビューション(Fedora, Ubuntu)も充実しています。
LINUXで自宅サーバーを構築・導入(Fedora9)
Fedora9のインストールの仕方から管理方法まで、詳しく載っています。 SearchManには情報がもりだくさんです。
マロンくん.NET
〜サーバ管理者への道〜
Linuxをサーバとして使用するための、いろいろな設定方法が載っています。 マロンくんもかわいいです。 なんといっても、マロンくんという名前がいいですね!!
日経Linux
今や数少なくなってしまったLinuxの雑誌。ニュースやガイドもあります。
Linux Square − @IT
@ITが提供する、Linux の情報が満載。 載っていない設定方法はないんじゃないでしょうか。
gihyo.jp…技術評論社
Linuxに限らず様々な技術情報が満載のサイト。 SoftwareDesign誌も、 ソフトウェア技術者は必見です。
SourceForge.JP Magazine
Linux に限らず、オープンソース関連の記事が網羅されています。
ITmediaエンタープライズ:Linux Tips 一覧
Tips というより FAQ 集でしょうか。わからないことがあれば覗きましょう。
IBM developerWorks : Linux
開発者向けですが、勉強になりますよ。
Yahoo!ニュース - Linux
Yahoo!のLinuxに関するニュース一覧です。
栗日記
システム管理とかと全然関係ありませんが、毎日栗の絵を描いています。
システム管理につかれちゃったとき、癒されたいときに、ご覧ください。:-)
WEB RANKING - PC関連
ランキングに参加してみました。押してやってください。

▼ 作ってみました

Add to Google

▼ せんでん




▼ 最近読んだ本

▼ 気に入ってる本