Akira's Commentary

VNCでX端末もどき

XvncサーバとVNCビューワを組み合わせて使うと、Xサーバの代用になります。 Xのアプリケーションを使う環境なら、Xvncも動作させることができるでしょう。 ですからXvncもどこかのマシンで動かせば、 手元のマシンのVNCビューワだけでXが使えるようになるわけです。

Xvnc Structure

ですが、このような形態で使うには 最初にXvncを起動しておかなければなりません。 また、その時に割り付けられたディスプレイ番号を Xアプリケーションでも、 ビューワでもいちいち設定しなければなりません。 これは結構面倒です。

やはり、ビューワを起動すると勝手にサーバが起動されて、 Xが使える状態になり、 ビューワを終了するとサーバと そこで動作していたアプリケーションも終了する、 つまり、X端末のように使えたら便利だと思いませんか?

と、VNCを使い始めた頃に妄想していたのですが、 同じことを考えて、しかも、 きちんと実現してしまった方がいらっしゃいます。 それが、Andre Moreira氏の iXvnc patch for VNC X-Server です。 これは、Xvncをinetd経由で起動するようにするものでして、 これを使うと、ビューワからのオンデマンドでXvncサーバが起動し、 またビューワを終了させるとサーバも (そのサーバで動作しているアプリケーションを含めて) 終了する、というものです。 これにxdmを組み合わせると気分はX端末そのものになります。

なお、iXvncパッチの機能は、 Xvnc3.3.3r2でXvnc本体に組み込まれました。 3.3.3r2以降のバージョンを使っている方は、 以下のパッチの入手、適用、ビルドは不要ですので、 読み飛ばしてください。

ソースとパッチを入手

iXvncパッチの機能は、Xvnc3.3.3r2でXvnc本体に組み込まれました。

iXvnc patch for VNC X-Serverは、 Xvncに対するパッチとして提供されていますので、 最初にXvncのソースを入手する必要があります。 XvncのソースはAT&T ケンブリッジ研究所の Downloading VNC のページから入手できます(1)。 XvncのソースはUnix Sourcesパッケージに含まれています。 これをダウンロードして展開しておきます。 ファイルは「vnc_unixsrc」ディレクトリ以下に展開されます。

iXvnc patch for VNC X-Serverには、 元のUNIX版のバージョンに対応して複数のパッチがあります。 現在(2000年1月)のバージョンは3_3_3ですので、 それに対応したパッチ(ixvnc3a.tgz)を入手します。

パッチを当てる

以下のディレクトリに移動し、そこでパッチ(ixvnc3a.tgz)を展開します。

cd vnc_unixsrc/Xvnc/programs/Xserver/hw/vnc

パッチといっていますが、ixvnc3a.tgz には

-rw-r--r-- root/root 20180 Sep 20 08:56 1999 init.c
--w------- root/root 12040 Sep 20 08:56 1999 sockets.c

の2ファイルが含まれていて、 Xvncのソースを置き換えるようになっています。 ですから、安全のため、 最初にこれらのファイルをバックアップしておいた方がいいでしょう。

cp init.c init.c.orig
cp sockets.c sockets.c.orig
chmod +w init.c sockets.c       リードオンリになっているので

で、パッチファイルを展開します。

gtar xzvf ixvnc3a.tgz
chmod 644 init.c sockets.c      リード禁止!になっていたので

後は、Xvncを作り直せばOKです。 ディレクトリ「vnc_unixsrc/Xvnc」で

make World

します。たっぷり時間がかかります。

なお、パッチを当てて作成されたXvncは、 -inetdオプションが追加され、 このオプションを付けた場合にのみ inetdからの起動が可能になります。 このオプションを使用しなければ、元のXvncと同じ動作になる、 ということですが、やはり不安ですので、 別の名前iXvncでインストールしました。

inetdの設定

iXvncをinetdから起動できるようにするには、二つのファイル

/etc/services
/etc/inetd.conf

を修正する必要があります。

/etc/services

inetdから起動されるVNCのサービスを定義します。 サービスの定義は

サービス名  ポート番号/プロトコル

というものです。 VNCサーバの画面サイズ、色数に応じていくつかのエントリを用意します。

vnc-800x600x8       5950/tcp
vnc-800x600x32      5951/tcp
vnc-1024x768x8      5952/tcp
vnc-1024x768x32     5953/tcp

ビューワからアクセスする場合には、画面サイズ、色数に応じて、 ディスプレイ番号:50、51、52、53、を設定してアクセスします。 ですが、実際に起動されたiXvncが使うディスプレイ番号は 別の値になります。

/etc/inetd.conf

こちらのファイルでは、 ビューワからのコネクションに対して起動されるプログラムを登録します。 /etc/servicesで定義したサービス名に合わせて設定します。

vnc-800x600x8   stream tcp nowait nobody プログラム アーギュメント
vnc-800x600x32  stream tcp nowait nobody プログラム アーギュメント
vnc-1024x768x8  stream tcp nowait nobody プログラム アーギュメント
vnc-1024x768x32 stream tcp nowait nobody プログラム アーギュメント

ここで、プログラムは、インストールしたiXvncのパス名です。

/usr/local/bin/iXvnc

アーギュメントは、サーバを起動する時のパラメタです。

iXvnc -inetd -query host -once -geometry 800x600  -depth 8 -cc 3
iXvnc -inetd -query host -once -geometry 800x600  -depth 32
iXvnc -inetd -query host -once -geometry 1024x768 -depth 8 -cc 3
iXvnc -inetd -query host -once -geometry 1024x768 -depth 32

パラメタについて説明しておきます。

-inetd
これで、inetdから起動されて動作するようになります。
-query host
これでxdmが有効になります。 iXvncは起動されるとここで指定されたホストに対して、 ディスプレイマネージメントを問い合わせ、 xdmのログイン画面が表示されることになります。
-once
Xセッション(.xsession)が終了したらサーバも終了します。 iXvncではこれによってサーバとビューワのコネクションが切れます。 なお、iXvncはビューワとのコネクションが切れたところでも 終了してしまいます。
-geometry 幅x高さ
サーバが生成する仮想Xデスクトップのサイズを指定します。
-depth 色数
デスクトップの Color Depthを指定します。
-cc 3
Color Depth 8ビットの場合には、PseudoColorで動作させます。 これを指定しないとTrueColorになり、一部のアプリケーションが 誤動作することがあります。

問題点、その他

  • -inetdで起動された場合にはいかなるコネクションも受け付けません。 httpコネクション(58xx)も受け付けませんので、 ブラウザからのhttp://host:58xxによるアクセスが使えません。 同じホストでhttpdを動かして、58xxでアプレットを返すように すれば何とか使えるそうですが...

    使い方の解説が出ていました。 こちらをご覧ください。

  • ビューワからのコネクションが切断されるとiXvncサーバも (そこで動作しているアプリケーションも含めて)終了します。 通常のXvncでは、ビューワが終了しても 仮想デスクトップはそのまま残ります。 この部分の違いに注意してください。
  • -inetdでXvncが起動されるようになっても、xdmが動作していないと グレイの画面が表示されるだけです。xdmの起動方法は、OSや デスクトップ環境によって異なりますので、一般的な解説は 難しいのですが、いくつか、役に立ちそうなweb pageがありますので 参考にされるとよいでしょう。
    ゼロ円でできるXサーバ WindowsでLinuxをリモート操作 [前編] [後編]
    Linux/GNOME用の設定方法が出ています。
    Setting up VNC on Linux
    英語での解説です。 Linux/KDE/GNOMEでのxdmの起動方法も含めて記載されています。
    FreeBSDハンドブック
    FreeBSDでの設定方法はここに記載されています。

トラブルシューティング

VNCのinetd接続を使おうとすると、結構トラブルに遭遇するようです。 ここではいくつかの対処方法をメモしておきます。

pingは届きますか?
pingが届かないのは論外ですね。 まずはネットワークがちゃんと設定されているかどうかを 見直してください。 このあたりの問題は各サイトのネットワーク管理者に聞いてください。
telnetで接続できますか?
/etc/servicesで登録したポートを指定して telnetで接続してみてください。 Xvncサーバが正常に起動されたならバージョン文字列 RFB 003.003が返ってきて応答待ちになります。
これが返されないなら、inetd周りの設定に問題があります。 設定を見直してください。 最近の環境ではセキュリティ設定がきつくなっているので、 セキュリティ関連の設定も見直す必要があるかも知れません。
バージョン文字列が返された直後に サーバ側でコネクションが落とされることもあります。 これは何らかの理由でXvncサーバが(エラー)終了するためです。 vncserverで起動した場合には ホームディレクトリの.vncの下に ログが記録されますのでそれを見ると原因が判るのですが、 inetdモードの場合には通常ではログが残されないために 原因追及が面倒です。
inetdモードで起動された場合、Xvncサーバは /usr/admディレクトリにログを書こうとします。 最近のUNIX系OSには通常はこのようなディレクトリはありませんので 結果としてログなしになってしまいます。 ですから/usr/admを用意して書き込み可能にしておけば ログが残りますので、それを見るといいでしょう。
なお、先日FreeBSD4.7にインストールした時には、xdmのデフォルト設定が サービスせず、になっていたため(以前はそうなっていなかったはずなのに)、 xdmが動作していなければ正常実行(ただしログインウィンドウが出てこない)、 xdmが動作しているとサービス拒否されて終了、となってしまいました。
スクリーンは表示されますか?
スクリーンが全く表示されないでビューワが終了するのであれば、 (上述のように)Xvncがエラー終了している可能性があります。 /usr/admを用意してログが残るようにして どのような原因で終了しているか調べてください。
ログインウィンドウは表示されますか?
一番多いトラブルがこれでしょう。 xdm (X Display Manager)が動作していてサービスを提供していれば、 ログインウィンドウが表示されます。 ログインウィンドウが表示されないなら、 xdmが動作しているかどうかをまず確認してみてください。 なお、実際のX Display Managerプログラムは環境によって異なります。 FreeBSDではxdm、GNOMEではgdm、Solarisならdtdm、 といったものになります。 設定方法についてはそれぞれのマニュアルをご覧になってください。
フォントの表示がおかしい
Xvncは通常のサーバとは別物ですので、 デフォルトでは異なったフォントを使用します。 そのため、通常のXサーバが特別なフォントを使っていると (Solaris/CDEで顕著ですが)、文字の表示がおかしくなります。 通常のXサーバのフォントパスを確認し(xset q)、 同じものをXvncの起動パラメタに設定すれば大丈夫です。
ただ、現在のXvncはTrueTypeフォントに対応していませんので、 TrueTypeフォントを使う場合にはフォントサーバ経由にする 必要があります(TTフォントに対応したバージョンもあるようです)。
動作しないアプリケーションがある
これは多くの場合、ビジュアルクラス、 またはエクステンションの問題です。 Xのアプリケーションは、理想的には、 いかなるビジュアルクラスであっても、 エクステンションがサポートされていなくても、 それなりに動作すべきなのですが、 現実には特定のビジュアルクラスを要求するもの、 特定のエクステンションに依存したプログラムにこと欠きません。
ですから、本来はアプリケーション側で対処すべき、 なのですが、現実問題としてはそうはいっていられませんね。 特定のビジュアルクラスを必要とするものについて、 そういうクラスをサポートしたXvncを起動して、 そこで動かすしかないでしょう。

問題は連携して動作する必要のあるアプリケーションが、 それぞれ異なったビジュアルクラスを要求する場合ですね。 何かいい解決方法ありませんかね。

エクステンションの問題に関しては、 いまのところは解決策はありません。 VNC単独であれば、 VNC for XFree86を 使えばある程度は解決できます。