VNC | ||
---|---|---|
HOME |
RedHat系では、VNCサーバは vnc-server パッケージ (RHEL/CentOS 6 以降では tigervnc-server パッケージ) で提供される。また、xinetd 起動にする場合は xinetd パッケージもインストールしておく必要がある。
RedHat系の /etc/hosts ファイルは伝統的に書き方が悪く、このあとの VNCサーバの設定でエラーが出る場合がある。
127.0.0.1 localhost.localdomain localhost centos51u
のようになっているのを、
127.0.0.1 localhost.localdomain localhost 192.168.0.8 centos51u.mydomain.com centos51u
のように直しておく。
筆者のお薦めとしては、RHEL/CentOS 5 (EL5) なら xinetd の wait=yes 方式、EL6 では Upstart。EL7 では systemd の socketユニットを併用した"方式2"がぎりぎり及第点で、環境によっては xrdp に逃げる。
この方法だと、やや動作が軽いように感じるのと、X が裏で常に稼働していなくて済むのでゲストのメモリが節約できる。また、VNCウィンドウ自体を ×で閉じた時にはセッションは存続し、次に同じユーザでログインすると同じセッションに再び接続できる(※)。ただし、VNC上で ログアウト してしまうと無応答のデスクトップ画面が残り、vncserver を再起動しなければならなくなるなど、セッションの管理が不気味。vncservers ファイルの中に書いている -IdelTimeout はそれを避けるための苦肉の策だ。
※ セッション維持が目的で SysVinit起動を選択するのはお勧めできない。上に述べたように rc起動はあまりにも粗雑だ。
/etc/sysconfig/vncservers を編集し、ユーザとディスプレイナンバーの対応、仮想ディスプレイの解像度などを定義する。下記のものは、root はディスプレイナンバー1 (つまりポート 5901)、hoge は 2 (ポート 5902) に紐付けし、仮想ターミナルのパラメータはどちらも「解像度 1024x768, 色深度 16bit」にする設定だ。このファイルは起動スクリプト /etc/init.d/vncserver によってシェルスクリプトの断片として読み込まれる (source される)。つまり、下記の記述はいずれも bash の配列の宣言である。-IdeleTimeout などその他のオプションは Xserver の man で見ていただきたい。
※ RHEL4.x の vncserver は `-nohttpd' オプションに対応しておらず、付けるとエラーになって vncserver が立ち上がらない。X11 XFIXESエクステンションも、エラーが出るようなら取り除くべし。
VNCSERVERS="1:root 2:hoge" VNCSERVERARGS[1]="-geometry 1024x768 -depth 16 -nolisten tcp -IdleTimeout 600 -nohttpd +extension XFIXES" VNCSERVERARGS[2]="-geometry 1024x768 -depth 16 -nolisten tcp -IdleTimeout 600 -nohttpd +extension XFIXES"
ホストに目的の UNIX ユーザでログインした状態で、VNCパスワードファイルを作る。VNC のパスワードとシステム上の UNIXパスワードは管理が全く別。下記操作によって ~/.vnc/passwd ファイルができる。
hoge$ vncpasswd Password: <タイプ> Verify: <再タイプ>
~/.vnc/ 下にその他の必要ファイルを作らせるため、VNCサーバを一旦手動で起動させ、すぐに終了させる。引数の `:2' はディスプレイナンバーで、前述の vncservers ファイルの定義と合わせる。起動時に `bad display name "centos51u.hoge.cxm:1" in "add" command' といったエラーが出たら、それは RedHat系デフォルトの、悪い /etc/hosts ファイルを直していないからだろう (既に述べたhostsファイルの整形の項を参照)。当該のユーザで;
hoge$ vncserver :2 hoge$ vncserver -kill :2
~/.vnc/xstartup ファイルを編集する;
#!/bin/sh unset SESSION_MANAGER <--アンコメントして有効化 exec /etc/X11/xinit/xinitrc <--アンコメントして有効化 [ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup <--これ以降は書いてあっても無意味 [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources xsetroot -solid grey vncconfig -iconic & xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" & twm &
exec で呼ばれている /etc/X11/xinit/xinitrc は (たとえ `exec' を `source' に替えたとしても)、最終的に Gnome (あるいはKDE) をまた exec で起動して終わるので、スクリプトのシェルプロセスはこの .vnc/xstartup にはもう帰って来ない。よって、上の例の場合、後半の `[ -x /etc/vnc/xstartup] && ...' 以下は一瞥だにされない。もし、`vncconfig -iconic &' (VNCサーバ/クライアント間でクリップボードによるコピー&ペーストを可能にする仕掛け) なども実行されるようにしたければ、`exec /etc/X11/xinit/xinitrc' の位置を下記のように変える;
#!/bin/sh unset SESSION_MANAGER [ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources xsetroot -solid grey vncconfig -iconic & exec /etc/X11/xinit/xinitrc #xterm -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" & #twm &
VNCサーバがエラーなく起動するかどうか確認;
root# service vncserver start
ホスト起動時に vncserver サービスが自動的に開始されるようスタートアップに登録;
root# chkconfig vncserver on
ホストの X-window 設定ファイル (/etc/X11/xorg.conf) は、こと VNCに関する限り、最近ではほとんどさわる必要がなくなった。そもそも、最近の Fedora Core や CentOS/RHEL 6 には xorg.conf 自体が既定では存在しない。また、Screen セクション内の Display セクションの解像度 (Modes) も、vncserver には影響がないようだ。 "1024x768" が書いてなくても、/etc/sysconfig/vncservers できちんと定義してあれば解像度 1024x768 が成り立つ。
こちらの場合、VNC画面上で ログアウト すると xinetd がセッションを殺すので、クリーンに終了することができる。VNCウィンドウを × で閉じた時も同じだ。ただし、裏側で常に X が待機しているせいなのか、割り当てメモリの少ないドメインでは、SysVinit起動の時よりも動きがやや重い気がする (※1 裏技あり)。ポート (ディスプレイナンバー) さえかぶらなければ SysVinit起動と両方待機させておくことも可能だ。
/etc/inittab のデフォルト runレベルは 5 にしなくてはならない。以下の設定に必要となる gdm (prefdm) は、 inittab (RHEL6ではupstart) の中で、ランレベル 5 でのみ起動するよう定義されているからだ。ここでランレベルを変更した場合は、以下の作業の前にゲストドメインを一度再起動しておく。
/etc/xinetd.d/ 下に下記のような内容のファイル xvnc (root:root 644) を作成する。ファイル名は任意。
service xvnc51 { socket_type = stream type = UNLISTED port = 5951 wait = yes user = hoge flags = IPv4 server = /usr/bin/Xvnc server_args = -inetd -query localhost -once -geometry 1024x768 -depth 16 -PasswordFile /home/hoge/.vnc/passwd +extension XFIXES log_on_failure += USERID cps = 1 30 instances = 2 per_source = 2 } service xvnc52 { socket_type = stream type = UNLISTED port = 5952 wait = no user = nobody group = tty flags = IPv4 server = /usr/bin/Xvnc server_args = -inetd -query localhost -once -geometry 1024x768 -depth 16 securitytypes=none +extension XFIXES log_on_failure += USERID cps = 1 30 instances = 2 per_source = 2 only_from = 192.168.122.0/24 192.168.1.0/24 }
protocol=tcp (または udp) を書くとうまくいかない。赤字で示している `type=UNLISTED' と port を書けば、後述の services ファイルへのポートナンバー登録は必要なくなる。`server_args' の X11 XFIXES エクステンション(ホームページ, 規格) は古い Linuxゲストにはないかもしれないので、エラーが出るようなら削除していただきたい。`cps' 以下はちょっとしたセキュリティ。
最初の例の `service xvnc51' として定義しているものが、筆者の最も気に入っているやり方だ。ポイントは `wait=yes' にしてある点。こうすると、VNCクライアント画面を × で閉じてもセッションは終わらない、つまり再度つなぎに行けばさっきの作業の続きができる。一方、ログアウトをすると、ちゃんとセッションは終了し、変なプロセスが残ったりはしない。新しくセッションを開始する際にパスワードを 2回打たなくてはならないのが玉に瑕だが、ある意味理想的な挙動が得られる。このパターンの場合、xinetd にはリモートホストの IPアドレスが分からないようで、`only_from' を入れたり tcp-wrappers (/etc/hosts.allow と hosts.deny) で IP規制するとつながらない。`flags=INTERCEPT' も試したがダメ。規制したければ iptables でも使うしかなさそうだ。
`wait=yes' のパターンの場合は、当該ユーザの VNCパスワードファイルを作成しておく必要がある。SysVinit起動方式の中で述べたように、hoge でログインした状態で vncpasswd を実行すればいい。
xinetd用VNCサーバ起動定義に `type=UNLISTED' と `port=port ' を書かない場合には、xvnc ファイル内の service で定義したサービス名を、ポートとプロトコルとともに /etc/service ファイルに加える。ポート番号は 5900 から 5960 の間が他のサービスと被りにくく無難だが、自分の環境の services ファイルをよく確認して決めること。
xvnc50 5950/tcp xvnc50 5950/udp xvnc51 5951/tcp xvnc51 5951/udp xvnc-hoge 5952/tcp xvnc-hoge 5952/udp
やり方はディストリビューションによって異なる。
`gdmsetup' とコマンドするか、Gnomeメニューの システム -> 管理 -> ログイン画面 を選び、GDM のセットアップを実行する。設定ツール自体が X-Window と gdm を使うので、テキストコンソールでは行えない。また、CentOS 5.1 では、root でログインした X-Window 上でしか設定GUI が呼び出せなかった。
リモート タブの スタイル: を リモートログインを無効にする 以外 にする。これにより XDMCP プロトコルが有効になる (※2)。
上記の代わりに XDMCP タブのあるリリースでは、XDMCPを有効にする にチェックを付ける。
設定を反映させるには gdm の再起動が必要なので、`gdm-restart' とコマンドして gdm だけを再起動するか、マシンをリブートする。なお、この手のディストリビューションでも、手動で custom.conf を編集する方法も使える。
Fedora Core 9 以降や RHEL6 では、gdmsetup が存在しない。そのため、XDMCP を有効にするにはこの方法しかない。GDM は 2.21 でコードがまったく新たに書き直された模様で、2.20 以前にあった複数サーバ定義機能が実装に至っておらず、gdmsetup も存在しないのだ。
/etc/gdm/custom.conf (RHEL4 は /etc/X11/gdm/gdm.conf) をテキストエディタで開き、[xdmcp] セクションに `Enable=true' と書く。ついでに、root での VNC ログインを許可したい場合は、[security] セクションに `AllowRemoteRoot=true' も書いておく。
root# service xinetd restart
使い心地としては xinetd の wait=yes の場合と同じとなり、具合がよい。xinetd だとVNCサーバを再起動する際に他の xinetd 所轄のサービスまで道連れになってしまうが、Upstart ならVNCサーバだけを停止したり再起動したりできるというのも利点だ。
xinetd 起動と同様。
Upstart-1.4 以降なら setuid と setgid ディレクティブを使って全てのコマンドやプロセスを特定のユーザおよびグループで実行することが可能なのだが、RHEL/CentOS 6 の Upstart はまだ 0.9.x なのでその手が使えない。そこで su を挟む。プロセスは、Upstartの発生させるシェルプロセス[親] => su のプロセス[子] => 正味の Xvnc プロセス[孫] という構造となる。`status xvnc51' で表示されるのは[親]のPIDだ。VNCクライアントを × で閉じると次回も継続して同じ画面につながる。対して、VNC画面上でログオフをすると、Xvnc プロセスが終了 => su が終了 => Upstartシェルプロセスが消失するが、ジョブ定義に respawn が指定しあるため Upstart がまたプロセスツリーを再発生させる。
# xvnc51 - VNC Server listening on :51 # # Starts Xvnc server env DISPNO=":51" env RUNUSER=hoge start on started rc RUNLEVEL=5 stop on started rc RUNLEVEL=[!5] console output respawn respawn limit 10 120 kill timeout 30 pre-start script su -s /bin/sh -c "/usr/bin/vncserver -kill $DISPNO >/dev/null 2>&1 || :" $RUNUSER end script script su -s /bin/sh -c "/usr/bin/Xvnc -query localhost -once \ -geometry 1280x1024 -depth 16 -PasswordFile /home/$RUNUSER/.vnc/passwd \ +extension XFIXES $DISPNO" $RUNUSER end script pre-stop script su -s /bin/sh -c "/usr/bin/vncserver -kill $DISPNO >/dev/null 2>&1 || :" $RUNUSER end script
xinetd の時と同様。
xinetd の時と同様。ただし、やらなくても一応は動く。
スタートscriptに `-query localhost -once' を使っているので、xinetd の時と同様に XDMCPを有効化する。
root# initctl reload-configuration root# start xvnc51 root# status xvnc51 root# stop xvnc51
RHEL/CentOS 7 では、サービスの起動フレームワークが SysVinit や Upstart に代わって、Systemd というやつにすげ替えられた。
systemd に牛耳られる RHEL/CentOS 7 では、ローカルのデフォルト起動モードが graphical.target (initでの runレベル5 に当たる) でも multi-user.target (initでの 3 相当) でも VNC は成り立つ。「ローカルコンソールは CLI にかぎる!」というスパルタンな人は、デフォルト Target をキャラクタモードにしておいてもよい。デフォルト Target を切り替えるには
root# systemctl set-default multi-user.target
でどうぞ。
まず、VNC の待ち受けポートを計画する。ここでは、5951 つまりディスプレイナンバー :51 で待ち受けると想定しよう。
この方式では、上で紹介した Upstart の方法や xinetd方式 の wait=yes の時と同じように、ログアウトすれば Xvnc プロセスがクリーンに終了するし × で閉じると次回も継続して同じ画面に接続できる。gdm/custom.conf の XDMCP 有効化は不要。
この方式では、VNCセッションから"ログアウト"すると vncserver プロセスが終了してリスポーンするのだが、時々、vncserver が "address already in use" と言って再立ち上げに失敗する。正確には、vncserver は起動しているけれども `netstat -lnt' で見てみるとポートがリッスンされていない。どうもうまくない。
tigervnc-server パッケージをインストールすると、/usr/lib/systemd/system/ に雛形 vncserver@.service がインストールされるので、これを xvnc@<DISP>.service として /etc/systemd/system/ 下へコピーする。この例なら、
root# cp /usr/lib/systemd/system/vncserver@.service \ /etc/systemd/system/xvnc@:51.service root# chmod 644 /etc/systemd/system/xvnc@:51.service
という塩梅だ。名前の後に @ の付いたこの種のユニットファイルは、Unit Template という少し特別なタイプで、@ と拡張子の間の文字列 (インスタンス文字列) がユニットファイル内の %i に代入される仕組みになっている。VNCのこのユニットファイルに関する限り、インスタンス文字列 がそのまま vncserver コマンドにメイン引数として渡されるので、@ の後に : (コロン) を忘れないように。そしてコピーしたユニットテンプレートを (かなり) カスタマイズする。User= の hoge を Linux 上のあなたのユーザに修正のこと。
[Unit]
Description=Remote desktop service (VNC)
After=syslog.target network.target
[Service]
Type=simple
User=hoge
PAMName=login
Restart=always
RestartSec=1
CPUShares=500
MemoryLimit=150M
ExecStartPre=-/bin/sh -c '/usr/bin/vncserver -kill %i >/dev/null 2>&1 || :'
ExecStart=/usr/bin/vncserver -geometry 1152x864 -depth 24 -fg %i
ExecStop=-/bin/sh -c '/usr/bin/vncserver -kill %i'
ExecStopPost=-/bin/sh -c '/usr/bin/vncserver -kill %i >/dev/null 2>&1 || :'
[Install]
WantedBy=multi-user.target
この方式では VNCパスワードファイルが必要なので、ユニットファイルの "User=" で指定したユーザで一旦 Xvnc を起動しすぐ終了する。その際にパスワードを設定する。
hoge$ vncserver :51 hoge$ vncserver -kill :51
ユニットが起動するかテストして自動起動を設定。
root# systemctl daemon-reload root# systemctl start xvnc@\:51.service root# systemctl enable xvnc@\:51.service
systemd で xinetd のような動作をエミュレートする方式。同じポート(ここでは 5951)で、複数のユーザがそれぞれ別々のセッションにログインできる。VNCクライアントを × で閉じることによって TCPセッションが終わり、それによりVNCセッションが必ず終了するので、ログアウトは必要でない。これは、TigerVNC WIKI にある Multi-user mode そのまんまである。xinetd の時と同様に XDMCPの有効化は必要だ。ユーザの ~/.vnc/ ディレクトリやVNCパスワードファイルは要らない。
/usr/lib/systemd/system/ の雛形 vncserver@.service を xvnc@service として /etc/systemd/system/ 下へコピーする。/usr/lib 側にあるのと同じファイル名だと上手く機能しない。これは[Install] セクションのない、他ユニットから呼ばれるのが専門のいわゆる Staticなサービスユニットというやつだ。
root# cp /usr/lib/systemd/system/vncserver@.service \ /etc/systemd/system/xvnc@.service root# chmod 644 /etc/systemd/system/xvnc@.service
そしてもうひとつ。xvnc.socket というユニットファイルも作る。拡張子の前は必ず対の service ユニットと同じ名前でなければならない(ただし@は不要)。
xvnc@.service
[Unit] Description=Remote desktop service (VNC) [Service] Type=simple User=nobody CPUShares=500 MemoryLimit=150M ExecStart=-/usr/bin/Xvnc -inetd -query localhost -once -geometry 1152x864 -depth 24 -SecurityTypes=None +extension XFIXES StandardInput=socket
xvnc.socket
[Unit] Description=Remote desktop socket (VNC) [Socket] ListenStream=0.0.0.0:5951 FreeBind=true Accept=true [Install] WantedBy=sockets.target
ListenStream の右辺はポート番号だけでも書式としては有効なのだが、それだと IPv6 もリッスンしてしまう。この例では IPv4 だけリッスンするよう x.x.x.x の形式で全てのインターフェースIPを示す 0.0.0.0 付けている。systemd には BindIPv6Only=true というディレクティブがあるが BindIPv4Only というディレクティブはないのだ。
自動起動にすべきは socket ユニットのほうのみ。socket がコネクションを受けて service を起動する仕組みだ。
root# systemctl daemon-reload root# systemctl start xvnc.socket root# systemctl enable xvnc.socket
CentOS 7.2 で試したところ、GNOME か polkit かのバグにより、VNCセッション上で一旦スクリーンがロックされると、正しいはずのパスワードを入力してもロックが解除できくなる。そのユーザのデスクトップの上部ツールバー右端から工具のアイコンをセレクト => プライバシー を開き、画面ロック をオフにしておこう。全てのアカウントでオフにしたいなら、「よろづ環境設定」に書いた GNOMEデスクトップ関連アプリのデフォルト値を変更したい の手順で、gschema.override ファイルに
[org.gnome.desktop.screensaver] lock-enabled=false
を含めればいい。
CentOS 7.2 では、VNCでデスクトップセッションにログインする前後に「カラーマネージメントされたデバイスを作成するには認証が必要です」というダイアログが何度も何度も出て疎ましい。よろず環境設定 を参照のこと。
単独ページに移しました。