■第5章 CVSの少し賢い使い方【サーバ編】 本章では、CVSの管理ファイルをカスタマイズし、CVSの使い勝手を自分の使用目的に合わせる方法について説明します。実際に管理ファイルを設定する際は、CVSを個人で利用する場合、複数の人と共同で作業する場合というように、二通りの状況が考えられます。本章では個人で利用する場合にでも、複数の人による共同作業の場合にでも共通する設定について考えてみたいと思います。複数の人による共同作業に特化した設定については、続く6章(P.161)で説明します。 ■■5.1 管理ファイルを設定しよう CVSの管理ファイルを設定すると、たとえば、コマンド実行時におこなう操作を自動化することができます。CVSを個人で使う場合にはもちろん便利ですが、複数の人で共同作業する場合には、必ず設定しておくべきです。 ■■■5.1.1 管理ファイルってどこにあるの? 管理ファイルは、リポジトリの直下にあるCVSROOTディレクトリの中にあります。本書では、リポジトリを/home/cvsrootに設置していますので、/home/cvsroot/CVSROOTの中で見つかるはずです。CVSROOTの中身をちょっと覗いてみましょう【図5.1】。 【図5.1】CVSROOTの中身 ▼ ls -a /home/cvsroot/CVSROOT . .#notify commitinfo history rcsinfo,v .#checkoutlist .#rcsinfo commitinfo,v loginfo taginfo .#commitinfo .#taginfo config loginfo,v taginfo,v .#config .#verifymsg config,v modules verifymsg .#cvswrappers .. cvswrappers modules,v verifymsg,v .#editinfo Emptydir cvswrappers,v notify .#loginfo checkoutlist editinfo notify,v .#modules checkoutlist,v editinfo,v rcsinfo ▲ 名前の先頭に.#のついたファイルはバックアップ・ファイルですので気にしないでください。checkoutlistとcheckoutlist,vのように、,vのついたファイル(RCSファイルともいいます)とペアになったファイルが管理者が設定をおこなうための管理ファイルです。 ■■■■historyファイル ここで、historyというファイルには,vのついたペアのファイルが存在しません。このファイルはユーザのおこなった動作をCVSが逐次記録するためのファイルです。add、commitなどを実行する度に、その情報が追加されていきます。historyコマンドでこのファイルの内容を抽出・整形して表示することもできます。自動的に書き換えられるものですから、管理者が編集する必要はありません。基本的にこのファイルはこのままそっとしておいてください。 ■■■■passwdファイル 初期状態では存在しない管理ファイルに、passwdファイルがあります。 passwdファイルは、pserverの設定の際に追加して使います。 詳しくは、5.2節「遠隔から使えるようにしよう」で説明します。 ■■■■cvsignoreファイル passwdファイルと同様、cvsignoreファイルも初期状態では存在しません。cvsignoreファイルも後から追加することができます。 使い方および設定の方法は、4.1節「個人環境を整えよう」で.cvsignoreに記述したものと同じです。無視すべきファイル名を記入しておくと、CVSはupdateのときにこれらを無視します。 両者の違いは設定の影響範囲です。.cvsignoreの設定は個人および作業コピー内にのみ影響を与えますが、管理ファイルcvsignoreの設定は、リポジトリ利用者全員に影響を与えます。 なお、この最初の状態では含まれていない管理ファイルに、passwd、readers、writers、users、cvsignoreの5つのファイルがあります。passwd、readers、writersファイルは、pserverの設定の時に追加して使います。passwdファイルについては、5.2節「遠隔から使えるようにしよう」で説明します。readers、writers、usersについては、第6章で説明します。cvsignoreの使い方および設定の仕方は、4.1節「個人環境を整えよう」で.cvsignoreに記述したものと同じです。パターンを書いておくと、updateの時にパターンにマッチしたファイルを無視するようになります。影響範囲が、個人および作業コピー内だったのが、リポジトリ利用者全員に拡大されるというだけです。 ここで主な管理ファイルと、関連するコマンド、およびその使用目的を【表5.1】にまとめておきます。 【表5.1】 管理ファイル名 関連するコマンド 使用目的 備考 config リポジトリ全体に影響する設定をおこなう passwd 遠隔から実行するコマンドすべて pserverで使用するパスワードを格納する 自動的には再構築されない checkoutlist checkout 新規に追加する管理ファイルを記述する modules commit、checkout、export、rtag、update モジュールに別名をつけ、コマンド実行時に外部プログラムを実行する commitinfo commit コミット前のチェックプログラムを指定する 共通構文 loginfo commit コミット後のログメッセージの処理をおこなう 共通構文 rcsinfo commit ログメッセージのフォーマットを指定する 共通構文 verifymsg commit rcsinfoと組み合わせてログの書式を検証する 継続 editinfo commit コミットのログを編集したり、評価したりするプログラムを指定する 使わない taginfo tag、rtag タグ操作時に外部プログラムを実行する 共通構文 cvsignore update cvsで管理しないファイルを見えなくする .cvsignore cvswrappers checkout、commit、update データの出し入れ時に特定のファイルに対してフィルタをかける 将来的には使わない
.cvswrapper notify watch、edit、unedit watch指定されたファイルに変更があったときの通知を制御する readers 遠隔から実行するコマンドすべて pserver経由のアクセスについて読み書きのできるユーザを指定する writersより優先 writers 遠隔から実行するコマンドすべて pserver経由のアクセスについて読み書きのできるユーザを指定する readersの方が優先 users notify notifyでメール通知をおこなう場合のユーザ名にメールアドレスを対応させる ■■■5.1.2 管理ファイルはどうやって編集するの? 気がつかれたと思いますが、,vが各管理ファイルについていたということは、これらの管理ファイルはバージョン管理されているということです。ほかのモジュールと違って、CVSROOTはそのディレクトリの中に、バージョン管理用の,vファイルと、その最新コピーが入っています。このため、管理ファイルを編集するには、次のようなどちらかの通常の作業方法でバージョン管理する必要があります。 方法1. 直接/home/cvsroot/CVSROOT内のコピーを編集し、RCSコマンドを介してバージョン管理する 方法2. checkoutして編集し、commitする CVSには、「checkoutして編集→commit」という通常の操作だけで、管理ファイルへの変更反映をおこなう仕組みが組み込まれています。この仕組みを利用する方が楽でしょう。つまり、方法2.を使うのが良いと思います。 まず、CVSROOTの作業コピーをcheckoutしてみましょう【図5.2】。 【図5.2】CVSROOTを手元に取ってくる ▼ % cvs checkout CVSROOT cvs checkout: Updating CVSROOT U CVSROOT/checkoutlist U CVSROOT/commitinfo U CVSROOT/config U CVSROOT/cvswrappers U CVSROOT/editinfo U CVSROOT/loginfo U CVSROOT/modules U CVSROOT/notify U CVSROOT/rcsinfo U CVSROOT/taginfo U CVSROOT/verifymsg ▲ 【表5.1】であげた16個のファイルのうち、passwd、readers、writers、users、cvsignoreを除く11個の管理ファイルがコピーされました。 このうち、試しにconfigファイルを編集してみましょう。configファイルの中に設定できるパラメータは、現在のところ、SystemAuth、TopLevelAdmin、PreservePermissions、LockDirの4つです。 このうち、SystemAuthパラメータは5.2節「CVSを遠隔から使えるようにしよう」の項目で詳しく説明します。 TopLevelAdminパラメータは、モジュールを取ってきたとき、モジュールの内部だけでなく、その上のディレクトリにもCVSディレクトリを作るためのパラメータです。何が嬉しいかといいますと、細々としたモジュールをまとめて扱うときに便利です。加えて複数のリポジトリを使い分けている利用者も、同じリポジトリを同じディレクトリにまとめることができるので、便利かもしれません。 PreservePermissionsパラメータは、ファイル属性を保持したい場合に設定します。4.2.5項「テキストファイル以外のファイルを扱う」で説明したように、シンボリックリンクも取り扱えるようになります。複数人での共同作業の場合にはあまり意味がありませんが、個人のバックアップ用に利用するような場合には設定するメリットがあるでしょう。 LockDirは、作業中にロックファイルを作るディレクトリを指定するためのパラメータです。このパラメータの設定により、リポジトリに書き込み許可を持たないユーザがリポジトリを利用できるようになります。WWWでの公開に伴い、httpdの実行ユーザがリポジトリを利用する必要があるようなときは、設定を考えるとよいでしょう。 ここでは、ほかでは紹介しないTopLevelAdminパラメータを設定し、その挙動を観察します。まず、cvs-1.10.8に付属するconfigファイルについてみてみましょう。 【図5.3】cvs-1.10.8についてくるconfigファイル ▼ # Set this to "no" if pserver shouldn't check system users/passwords #SystemAuth=no # Set `PreservePermissions' to `yes' to save file status information # in the repository. #PreservePermissions=no # Set `TopLevelAdmin' to `yes' to create a CVS directory at the top # level of the new working directory when using the `cvs checkout' # command. #TopLevelAdmin=no ▲ 最初configファイルには、SystemAuth、PreservePermissions、TopLevelAdminの3つのパラメータがコメントとして記述されています。LogDirについては記述がありません。ここでは、実験的に最終行の先頭の#を外して有効にし、かつTopLevelAdmin=yesに書き換えます。編集後このconfigファイルをcommitします【図5.4】。 【図5.4】configファイルをcommitする ▼ % cvs commit -m "TopLevelAdmin Test On" config Checking in config; /home/cvsroot/CVSROOT/config,v <-- config new revision: 1.10; previous revision: 1.9 done cvs commit: Rebuilding administrative file database ▲ commitの手順自体は、通常のモジュールと同じですが、最後にリポジトリ側の管理ファイルを作りなおしているところがちょっと違います【図5.4 6行目】。 次に、別のディレクトリに作業コピー(対象とするモジュールは何でもよい)を作ってみます【図5.5 1行目】。 【図5.5】別の場所に作業コピーを取ってみる ▼ % cvs -d /home/cvsroot checkout cvstest cvs checkout: Updating cvstest U cvstest/fish.jpg (中略) U cvstest/test2.txt % ls -F CVS/ cvstest/ % ls -F CVS Entries Entries.Log Entries.Static Repository Root % cat CVS/Entries.Log A D/cvstest//// % cat CVS/Root /home/cvsroot % cat CVS/Repository . ▲ すると、今までできなかった、CVSというディレクトリがモジュールと同じ場所にできていることを確認できます【図5.5 6-7行目】。中身があるのはひとまず、Entries.LogとRoot、Repositoryです。これで、CVSROOT環境変数や-dオプションを使ってリポジトリを切り替えなくても、このディレクトリに入れば、同じリポジトリに対する操作が可能となりました。 ■■5.2 遠隔から使えるようにしよう ■■■5.2.1 CVSを遠隔から使うにはどうすればよいの? CVSコマンドを使って遠隔のリポジトリにアクセスするには、CVSROOT環境変数もしくは-dオプションで、リポジトリを「接続に必要な情報を含んだ形で」指定するだけです。その指定形式は、【図5.6】のようになります。 【図5.6】遠隔リポジトリの指定形式 ▼ :接続方法:ユーザ名@サーバ名:サーバ上でのリポジトリパス ▲ たとえば、mikaというユーザが、pserverという接続方法で、cvs.mydomain.comというサーバ上の、/home/cvsrootというリポジトリから、cvstestというモジュールをcheckoutする場合は、次のように指定することになります。 ▼ cvs -d :pserver:mika@cvs.mydomain.com:/home/cvsroot checkout cvstest ▲ 接続方法には、ext、server、pserver、gserver、kserver、forkの6つの種類があります。また、これとは別に、明示的にローカルであることを示すために、localという接続方法も指定できます。localを用いた場合は、ユーザ名とサーバ名を指定する必要はありません。nserverという方法もあるそうですが、CVSの本流にまだ取り込まれていないので、本書では扱いません。 ■■■■どの接続方法を使えばよいの? 接続方法は、ユーザの環境や用途によって使い分ける必要があります。どんなサーバにもいえることですが、使い勝手とセキュリティのトレードオフを考慮する必要があります。つまり、設定が簡単な方法は一般にセキュリティが低く、セキュリティの高い方法は初期設定や使い方が難しいのです。通常、CVSをサーバにするには、extとpserverのどちらかの接続方法を選択するのが一般的です。extとpserverの接続方法を分類すると、【表5.2】のようになります。 【表5.2】接続方法の分類 サーバタイプ 外部プログラム 認証 データの暗号化 必要設定 用途 ext(server) rsh(なし) rhosts認証 なし rhostsの設定 イントラネットでの共有 ext ssh sshの認証 sshにより暗号化 環境変数CVS_RSHにsshを設定 インターネットでの共有 pserver なし 独自passwdファイル なし pserverの設定 インターネットでの公開 gserver、kserver、forkは、あまり一般的でないため、簡単な説明に止めます。gserverとkserverはKerberosという認証システムを使用しており、使用にあたっては、サーバ、クライアントともにKerberosが組み込まれている必要があります。Kerberosは米国の暗号方式の輸出問題に絡んで日本ではあまり普及していません。gserverはKerberos 5、kserverはKerberos 4いうKerberosのバージョンにそれぞれ対応しています。 forkは実行すると、クライアントとサーバの2つのプロセスに分かれて通信をおこない、データをやり取りします。これは、デバッグのための機能ですので、プログラマ以外の利用者は気にする必要はありません。 ■■■■extって何? extを指定すると、CVSは接続するために外部プログラムを呼び、そのプログラムを介して接続先のシステムに登録されたユーザで認証をおこないます。接続に利用する外部プログラムは環境変数CVS_RSHで設定します。CVS_RSHが設定されていない場合は、rshを呼びます。しかし、rshはパスワードもそのまま流れますし.rhostsや/etc/hosts.equivなどではかなり安易に相手ホストを信用するような設定をおこなうため、よほど信頼のおけるイントラネットでないと、実際に使用することはできません。一般に、通信が暗号化されていないログイン方法だと、パスワードもデータもそのまま流れてとても危険です。インターネットでの利用はもちろん、イントラネットでもなるべく避けた方がよいでしょう。筆者のお勧めは、外部プログラムとしてsshを利用する方法です。sshを使えば、ユーザ認証もデータ転送も暗号化されます。 なお、sshの設定、利用方法は本書の範囲を超えていますので割愛させてもらいます。Yahoo!などのサーチエンジンで検索すれば関連する情報を入手することは難しくないでしょう。2000年12月現在、OpenSSHが評判がよいです。 OpenSSHはRedHat Linux 7には標準で入っていますので、man sshなどと実行して、利用方法を確認してください。RedHat Linux 6.x以前では、別途インストールが必要です。 もし、sshが導入されていれば、環境変数CVS_RSHにsshを設定し、パスワードやパスフレーズを入力することで接続できるようになります。環境変数CVS_RSHは次のように設定します。 CSH系のシェルを利用している場合 setenv CVS_RSH ssh SH系のシェルを利用している場合 CVS_RSH=ssh; export CVS_RSH 環境変数の設定後、extを用いたリポジトリを指定するコマンドを実行してみると【図5.7】のようになります。 【図5.7】SSHを使ってコマンドを実行してみる(プレーンパスワード) ▼ % cvs -d :ext:mika@localhost:/home/cvsroot checkout cvstest mika@cvs.mydomain.com's password:XXXXXX cvs server: Updating cvstest U cvstest/test.pl U cvstest/test.tex ▲ この例では、sshの環境設定をおこなっていないので、システム・パスワードを尋ねられます【図5.7 2行目】。これに正しく入力すると接続がおこなわれ、接続先でcvsのコマンドがサーバモードで実行されます。さらにその結果の出力がネットワークを介して送られ、それをクライアント側で処理することで、遠隔リポジトリでも同じように利用することができます。 なお、接続先のcvsコマンドが一般的でない場所にセットアップされていると、まれに失敗することがあります。シェルの初期化ファイルでプログラムの検索パスを設定できればよいのですが、それでもうまくいかないことがあります(ええ、筆者はつい先日遭遇しましたとも)。こういう場合にクライアント側でできる解決策が1つあります。それは環境変数CVS_SERVERを設定することです。 たとえば、接続先のcvsが/home/hoge/binにあるとすると、CVS_SERVERを/home/hoge/bin/cvsに設定すればしのげます。 通常はシステムのパスワードをそのまま使うのではなく、RSA公開鍵暗号による認証をおこないます。手順はやや複雑なものとなりますので、ssh関係のホームページで調べてください。1つポインタを挙げておきます。 ▼簡単SSH URL http://www.netlab.is.tsukuba.ac.jp/~one/ssh/ なお、serverという接続方法は、CVS内部に実装されたrshを利用して接続する方法で、CVSの種類によっては、使えないでしょう(筆者はこれが使える実装に出会ったことがありません)。 ■■■■pserverって何? pserverはpassword serverの意味です。システムのパスワード・ファイルとは別のパスワード・ファイルを作成することができ、そのファイルに書かれたユーザ名とパスワードに基づき認証をおこないます。この方法のよいところは、システムに普通にログインするためのユーザ名とパスワードとは別にpserver用のユーザ名とパスワードが設定できるので、外部からシステムのユーザ情報を隠せるということです。しかし、パスワードやデータは暗号化されませんので、機密性を要する用途には使えません。インターネット上でデータを公開するなどの用途には使えるでしょう。さらに通信路を暗号化したいという場合は、SSL認証を使ったstunnelなどを利用するとよいと思いますが、筆者は実際に運用したことはありません。 では、pserverの設定方法について具体的に説明していきましょう。pserverの設定は、「管理ファイルの設定」と「サーバとしての設定」という2つの手順からなります。 ■■■■管理ファイルの設定って何? CVSがpserverとして働くときは、ユーザ認証をおこないアクセスが許されたユーザかどうかチェックします。この認証を正しく設定しておかないと、意図しない人物からアクセスされ危険です。特に自分が何をしているのかよくわからない場合には、セキュリティ・レベルをきつめに設定しておきましょう。pserverの認証に関わる管理ファイルは、configとpasswdです。passwdファイルは、初期状態では存在しませんから、自分で作成して追加することになります。 ■■■■■@configファイルの設定 まず、管理ファイルconfigでの設定です。 設定項目は1つだけです。SystemAuthというパラメータを設定できるのですが、それをnoにしておきます【図5.8】。 【図5.8】configファイルの変更部分 ▼ SystemAuth=no ▲ このパラメータは、認証要求のあったユーザがpasswdファイルに登録されたユーザでなかった場合に、システムのユーザとして認証するかどうかを決定します。つまりmikaというユーザ認証の要求があり、かつ、このユーザがpasswdファイルに登録されていなかったときに、システムのユーザにmikaがいるか調べるかということです。 逆にSystemAuth=yesに設定すると、システムのユーザまで対象にします。SystemAuth=noにしておけば、passwdファイルのユーザのみを認証対象にします。なるべく、対象を絞っておくためにnoにしておきましょう。システムのユーザを対象とする危険性は、ネットワーク中をシステム・パスワードが流れてしまう点にあります。なお、passwdファイルでのユーザ名およびパスワードを、システムのものと同じにしてしまったら意味がありません。違うものを使うようにしましょう。 ■■■■■Apasswdファイルの作成と登録 ユーザの制限が終わったら、アクセスできるユーザを設定しないと誰も使えません。ということで、passwdファイルにアクセスできるユーザを登録していきます。 この手法の最大の問題点は、ユーザのパスワードを暗号化してpasswdファイルに書かなければならないのに、暗号化の手段をCVSが提供していないということです。つまり、どこからかパスワードを暗号化するツールを取ってくるか、自分でごりごり作る必要があります。あるいは、passwdコマンドでユーザのパスワードを変更して、/etc/passwd(もしくは/etc/shadow)に生成されたパスワードをカット・アンド・ペーストしてくる手もあります。しかし、これはホストのroot権限がないと難しいかもしれません。筆者はWebサーバであるApache httpdについてくる、htpasswdを流用して使っています。 自力でごりごり作る場合は、perlのcrypt関数を利用するのが簡単だと思います。基本は、crypt("pass phrase", "xx")という形で、暗号化したい文字列を第1引数に、それにちょっと味付けをするための塩(salt)を第2引数に加えます。saltに渡せるのは、[a-zA-Z0-9./]のうち任意の2文字です。たとえば、【図5.9】のように、パスワードを^Hi-h0&=に、saltを.0にした場合【1行目】、.0mE4ugRRj9r.という文字列が生成されます【2行目】。 saltを考えるのも面倒なら、それをランダムに生成するためのコードをつけてスクリプトとして用意しておきましょう。 【図5.9】暗号化された文字列を得る ▼ % perl -e 'print crypt("^Hi-h0&=", ".0"), "\n";' .0mE4ugRRj9r. ▲ どんな方法でもよいですが、パスワードが暗号化できたら、passwdファイルを作成します。passwdファイルには1行に一人のユーザを設定します。1行の書式は次のようになります。 【図5.10】passwdファイルの1行の書式 ▼ CVSのユーザ名:パスワード:システムのユーザ名 ▲ ここで、第1項目のCVSのユーザ名と、第2項目のパスワードが、pserverにアクセスするためのユーザ名とパスワードを意味します。第3項目のユーザは、第1項目のユーザ名でアクセスした場合に、実際にどのシステム側ユーザとしてコマンドが実行されるかを設定する部分です。たとえば、bmikaとanonymousというユーザを設定してみると、【図5.11】のようになります。 【図5.11】完成したpasswdファイル ▼ bmika:ROHNP9.5MUyIs:mika anonymous:gB/FnBTDLRODw:anon ▲ bmikaとanonymousはシステム内では実際には、それぞれmikaとanonというユーザに該当することになります。 ■■■■サーバの設定って何? CVSは独立したサーバとしては動きません。つまり、「起動するとバックグラウンドに入り、待ち受け、通信などの全ての処理を自力でおこなうようなサーバではない」ということです。その代わりに、UNIXで通信の待ち受けを肩代わりしてくれるシステム、inetd(RedHat Linux 7ではxinetd)を利用します。telnetやftpもこのinetdを利用しています。inetdはそういったプログラムの代わりに、あらかじめ指定されたポートを見張り、通信の要求がくるのを待ち受けてくれます。そして、指定のポートに接続要求が来たら、接続を確立しポートに割り当てられたプログラムを呼び出してくれます。どのポートがどのプログラムに対応し、どのように呼び出せばよいかという設定は、/etc/inetd.confというファイルに記述します。cvsのpserverを設定するためには、inetd.confに【図5.12】のような行を追加します。 図では行が折り返されていますが、改行しないように注意してください。改行してしまうと、引数が途中で切れてしまうため、正常動作しません。 【図5.12】/etc/inetd.confへの追加(tcpdを挟む場合) ▼ # CVS pserver cvspserver stream tcp nowait root /usr/sbin/tcpd /usr/bin/cvs -f --allow-root=/home/cvsroot pserver ▲ ここで、第1項目のcvspserverはポート番号です。次の第2、3、4項目のstream、tcp、nowaitというのは通信方法で、第5項目のrootがプログラムの実行ユーザを指定しています。第6項目が呼び出すプログラムのパスを指定する場所ですが、通信の制限をおこなうために、CVS本体へのパスを直接書くのではなく、一旦tcpdというプログラムを間に挟む設定にします。次の第6項目以降が実際に呼び出されるプログラムと、その引数(-f、--allow-root=/home/cvsrootとpserver)になります。 引数のうち、pserverというのがCVSをサーバとして動作させるためのコマンドです。全体にかかるオプション、--allow-rootオプションはアクセスできるリポジトリを制限しています。つまり、サーバを介した状態では/home/cvsrootというリポジトリにしかアクセスできないということです。このオプションは必ずpserverと一緒に使われます。 ちなみに複数のリポジトリにアクセスできるように、--allow-rootを複数設定しようとすると、inetd.confの一行に設定可能な文字数を越えてしまいます。そういうときは、シェルスクリプトでCVSコマンドをくるんで、そのシェルスクリプトを呼び出すなどの工夫が必要です。 また、-fオプションは環境変数を無効化するためのオプションです。-fがないとroot(実行ユーザ)の環境変数が有効になってしまうようです。ただし、初期設定ファイルを各ユーザ毎に見にいくようにするためには、これだけではうまくいかないことも多いようで、UNIXの環境変数を操作するenvコマンドを利用し、CVSを実行するときの環境変数(特に環境変数HOME)を無効化する必要があります。envはオプション-iで無効化をおこないます。たとえば、【図5.12】を【図5.12-2】のように変更します(【図5.12】同様、改行しないように注意)。 【図5.12-2】envを使って無効化する ▼ # CVS pserver cvspserver stream tcp nowait root /usr/sbin/tcpd /usr/bin/env -i /usr/bin/cvs -f --allow-root=/home/cvsroot pserver ▲ tcpdは、/etc/hosts.deny、/etc/hosts.allowといったファイルで利用者の接続を制限をします。これらの設定方法などは、本書の範囲を超えていますので、各自で調べてみてください。ここでは、自マシン(localhost)と自ドメイン(localdomain)のみに接続許可を出す設定例を示します【図5.13、図5.14】。 ドメイン名(mydomain.com)とネットワーク(192.168.0.0)、それからネットマスク(255.255.255.0)は各自の環境にあったものを設定しましょう。 【図5.13】/etc/hosts.deny ▼ ALL: ALL ▲ 【図5.14】/etc/hosts.allow ▼ ALL: localhost 127.0.0.1 .mydomain.com 192.168.0.0/255.255.255.0 ▲ tcpdはインターネットに直接接続する計算機の自衛方法として基本的なプログラムです。なるべく使えるようにしておいた方がよいと思います。パッケージ名はtcpwrapperです。最近のRedHat Linuxの配付セットには、はじめから含まれています。もし、パッケージが見つからず、インストール方法も分からないという場合は、危険ですが、CVSを直接呼び出すように設定することもできます【図5.15】。また、公開サーバで一般利用者のアクセスを制限する必要がないという場合も、このように設定します。 【図5.15】/etc/inetd.confへの追加(tcpdを挟まない場合) ▼ # CVS pserver cvspserver stream tcp nowait root /usr/bin/cvs cvs -f --allow-root=/home/cvsroot pserver ▲ なお、/etc/inetd.confにおける最初のポート番号の指定で、cvspserverという文字列を指定しましたが、あらかじめ/etc/servicesの中にポート番号の別名としてcvspserverが登録されていることが前提になります。最近のRedHat Linuxではあらかじめ別名が定義されていますが、ほかのOSを利用している場合は記述を確認し、定義されていない場合は、【図5.16】のような行を追加しておいてください。 【図5.16】/etc/servicesの設定部分 ▼ cvspserver 2401/tcp # CVS client/server operations cvspserver 2401/udp # CVS client/server operations ▲ /etc/inetd.conf、/etc/servicesの設定が完了したら、inetdにその変更を通知しましょう。変更の通知は再起動でもよいですし、killコマンドでHUP(ハングアップ)信号を送りつけ(kill -HUP)ても構いません。RedHat Linux 6.xでは、起動スクリプトを利用するのが簡単です。 【図5.17】のように/etc/rc.d/init.d/inetに引数restartを指定して、inetdを再起動しましょう。 【図5.17】inetdの再起動(RedHat Linux 6.x) ▼ /etc/rc.d/init.d/inet restart ▲ Solarisにも起動スクリプト(/etc/init.d/inetsvc)はあるのですが、inetd以外にも余計なものを沢山動かしてくれます。このため筆者はもっぱらkill -HUPで再初期化をおこないます。具体的にはinetdのプロセス番号をpsコマンドで探し【図5.18 1行目】、そのプロセス番号にHUP信号をkillで送りつけます【図5.18 3行目】。SolarisのpsコマンドはSysV系で、BSD系とはオプションが異なります。詳しくは、manで調べてください。オプションの差異が気になる場合は、/usr/ucbの下にあるpsコマンドを使うとよいでしょう。 【図5.18】inetdの再初期化(Solarisでkill -HUPコマンドを実行する) ▼ % ps -ef | grep inetd root 120 1 0 04:01:21 ? 0:00 /usr/sbin/inetd -s % kill -HUP 120 ▲ RedHat Linux 7.xでは、inetdがxinetdに置き換わっています。初期設定ファイルの書き方も大幅に変更されました。しかし、書く内容自体は、ほとんど変わりません。上記のように「tcpdを使用しない」設定をおこなうファイルを【図5.19】に示します。これを、/etc/xinetd.dディレクトリ以下にcvspserverという名前で配置します。ファイル名はおそらく任意だと思いますが、サービス名と一緒にしておきます。 【図5.19】/etc/xinetd.d/cvspserver ▼ service cvspserver { socket_type = stream wait = no user = root server = /usr/bin/cvs server_args = -f --allow-root=/home/cvsroot pserver } ▲ 1行目のserviceは/etc/servicesに記述したポートの別名を書きます。次に、socket_type、wait、userといった項目に前と同じようにstream、no、rootを設定します。 serverというのが実行されるプログラムであり、/usr/bin/cvsを設定します。 このとき、CVSは引数を必要とするので、その引数-fと--allow-root=/home/cvsroot pserverをserver_argsに書きます。 ちなみに、もし、envで環境変数の初期化をおこなう場合には、serverに/usr/bin/envを、server_argsに"/usr/bin/cvs -f --allow-root=/home/cvsroot"を設定します。筆者の環境では、tcpwrapper(tcpd)の動作は、serverに書く、書かないに関わらず同じでした。この場合、tcpwrapper(tcpd)の動作を書かなくても、/etc/hosts.deny、/etc/hosts.allowで制御できるのだと考えます。 このファイルを/etc/xinetd.d/cvspserverとして置いたら、xinetdを再起動します【図5.20】。kill -HUPではうまくいきませんでした。 【図5.20】xinetdの再起動(RHL7.x) ▼ /etc/init.d/xinetd restart ▲ inetdを設定した後は、まず同じ計算機上からtelnetを使って接続できるか確認します。具体的には【図5.21】のようにホスト名とcvspserverを指定して、telnetを実行します。 【図5.21】telnetでの接続テスト(接続が成功した場合) ▼ % telnet localhost cvspserver Trying 127.0.0.1... Connected to xxx.xxx.xxx. Escape character is '^]'. cvs [pserver aborted]: bad auth protocol start: Connection closed by foreign host. ▲ 接続できると、3行目にConnected to xxx.xxx.xxxというようなメッセージが表示されます。表示されずに、【図5.22】のようなConnection refusedメッセージが表示されてしまった場合は、うまく設定できていません。再度設定を見直してください。 【図5.22】接続が失敗した場合のメッセージ ▼ telnet localhost 2402 Trying 127.0.0.1... telnet: Unable to connect to remote host: Connection refused ▲ /etc/inetd.confの記述で間違いやすいのはコマンドのパスです。また、/etc/servicesを自分で書き換えた場合は、ポート番号の別名の綴りもチェックした方がよいかもしれません。なお、接続に失敗した場合、Enterキーなどを入力すれば、「手順と違う」と表示され、CVSから強制的に切断されます。もちろん、Cntl-]でいったんtelnetの対話モードに復帰し、終了しても構いません。 ■■■■CVSクライアントからの接続テスト inetdで接続できることを確認したら、次はCVSクライアントから接続できるかテストしてみましょう。CVSでクライアントから接続する手順は、次のようになります。 ■■■■■@コマンドを使って、認証し認証情報を保存する CVSのloginコマンドを実行すると、指定されたリポジトリに接続し、パスワード入力を求められます【図5.23】。パスワードを入力すると、CVSサーバへ接続して、認証をおこないます。 【図5.23】loginしてpasswordを保存する ▼ % cvs -d :pserver:bmika@localhost:/home/cvsroot login (Logging in to bmika@localhost) CVS password:XXXXXX ▲ 認証が成功するとユーザのクライアント側のホームディレクトリにある.cvspassというファイルにその情報が格納されます。 【図5.24】~/.cvspass ▼ :pserver:bmika@localhost:/home/cvsroot A:0=:0]0 ▲ ■■■■■A任意のCVSのコマンドを実行する 一度.cvspassに認証情報が保存されると、ほかのコマンドの実行をサーバに依頼するときにも、その情報が自動的にサーバへ送信されます。 実は、コマンドを実行する度に、この.cvspassの情報を元に認証がおこなわれているのです。これは、コマンドの実行が一回一回独立しているためです。CVSには、前のコマンドの実行と、次のコマンドの実行が同じ人物かどうかを知るすべがありません。 そのため.cvspassの情報をもとに、コマンドの利用者が同じかどうか判断するという仕組みになっています。 ■■■■■BCVSのlogoutコマンドを使って、認証情報を除去する .cvspassに認証情報を保持しておいてもよいのですが、第三者が同じ環境で作業する場合や、そもそも「気持ち悪いな」という場合は、logoutコマンドを使って.cvspassの認証情報を削除しておきましょう。削除した場合には当然、次回のloginで再び認証情報を格納するところからはじめる必要があります。 以上の作業が成功したら、外部から同じように接続してみてください。外部から接続できない場合は、tcpdを介した場合の制限や、外部のファイアーウォールの影響による制限などといった原因が考えられます。サーバの運用には複雑な要因が絡んできますので、正常に動かすには、問題の原因を把握し、ひとつ一つ取り除いていくことが大事です。 ■■5.3 漢字コード変換を設定しよう Meadow/Mule for Win32や、複数の文字コードに対応しているエディタを使用していても、たとえば、TeXのファイルなどでは、UNIX環境ではEUCコードしか通らないとか、Windows環境ではSJISコードしか通らないということがありますね。こんなときは、やはりTeXのファイルは利用者の環境に合わせて文字コードを変換したいという考えが浮かぶでしょう。ネットワークを構成するホストの環境はさまざまですから、手元の計算機を様々な環境に適合するように調整しておくことは、後々自分の利益にも繋がります。本節ではCVSをEUCとSJISの2つの漢字コードに対応できるよう設定してみたいと思います。 ■■■5.3.1 cvswrappersを設定しよう CVSをknjwrp patchをあててコンパイルすると、管理ファイルcvswrappersに【図5.25】のような記述が追加されているはずです。 【図5.25】cvswrappersに追加された漢字コード変換のための行 ▼ #*.c -f '/usr/lib/cvs/contrib/wrapnkf -s %s' -t '/usr/lib/cvs/contrib/wrapnkf -e %s %s' -s ▲ この行を説明してみましょう。まず、#はコメント行の意味で、この行は実際には機能していません。この行を元に自分の環境に合ったカスタマイズをおこないます。最初の*.cはファイルのパターンを意味します。このパターンに適合したファイルに対して、その行の残りの部分の処理が適用されます。残りの部分は、-f、-t、-sというオプションとそれらの引数の並びで構成されています。 -fオプションはfromの意味でリポジトリから外部に出ていくファイルに対して適用されるフィルタを指定するためのものです。 -tオプションはtoの意味で外部からリポジトリに入ってくるファイルに対して適用されるフィルタを指定するためのものです。 最後に-sオプションはknjwrp patchで拡張された書式で、-sがついている場合のみ、remote-clietについてcvswrappers処理を有効にします。-sオプションは漢字コードを変換する場合は書いておいてください。-fオプションと-tオプションには/usr/lib/cvs/contrib/wrapnkfという同じフィルタが指定されていますが、その引数-sと-eで動作が切り替えられています。 なお、このフィルタはknjwrp patchをあてると自動的にインストールされます。 ■■■■漢字コード変換フィルタを作ろう さて、フィルタはどのような仕組みになっているのでしょうか? /usr/lib/cvs/contrib/wrapnkfの中を覗いてみましょう【図5.26】。このフィルタはソースツリーの中のcontribの下に作られます。 【図5.26】wrapnkfの中身 ▼ #! /bin/sh # # wrappper nkf filter for cvs-server/windoze-clients # # Usage: wrapnkf kanji_code infile [outfile] # ACK=/usr/local/bin/ack NKF=/usr/local/bin/nkf opt=$1 infile=$2 outfile=$3 if [ $opt = "-e" ] ; then $ACK -u -e -z $infile > /tmp/ack-cvs$$ mv -f /tmp/ack-cvs$$ $outfile elif [ $opt = "-s" ] ; then $NKF -s $infile > /tmp/nkf-cvs$$ mv -f /tmp/nkf-cvs$$ $infile fi; ▲ wrapnkfの実体はシェルスクリプトで、内部でackとnkfという一般的な漢字コード変換プログラムを呼び出しています。ackおよびnkfは、フリーウェアとして配布されています。それぞれのホームページからダウンロードしてインストールしてください。インストール方法はMakefileを自分の目的に合わせて修正し、makeし、適当な場所へ実行ファイルほかをコピーするだけです。RedHat Linuxの日本語版にはnkfが含まれています。さらにDebian GNU/Linuxディストリビューションでは、ackもパッケージとして用意されています。 ▼nkfのホームページ(琉球大学 河野 真治さん) URL http://rananim.ie.u-ryukyu.ac.jp/~kono/software.html ▼ackのホームページ(VECTOR内 小笠原 博之さん) URL http://www.vector.co.jp/soft/unix/util/se064384.html 実際の設定作業に取りかかる前に、環境における漢字コードの違いを整理しておきましょう。UNIXとDOS/WIndowsのファイル形式には、次の違いがあります。また、DOS/Windowsのファイルには半角仮名が含まれていることがあり、これらはUNIX環境で問題を引き起こすことがあります。そのため、UNIXにファイルを転送する場合には、半角仮名を全角仮名へ変換しておく必要があります。 【表5.4】各環境でのファイルの違い プラットフォーム 漢字コード 行末 ファイル終わり(EOF) UNIX EUC LF(0x0a) DOS/Windows SJIS CR/LF(0x0d,0x0a) 0x1a(Cntl-Z)がつくことがある Mac(おまけ) SJIS CR(0x0d) ackは、DOS/Windows環境からUNIX環境へ、ファイルを適合させるために必要な変換を、次の3つのオプションでおこないます。 【表5.5】ackのオプションの意味 オプション 意味 -e 出力コードをEUCにする -u 入力の0x0d(CR)および0x1a(Cntl-Z)を取り除く -z いわゆる半角仮名→全角仮名変換をおこなう なお、同じ変換はnkf1.92でもおこなうことができます。0x1a(Cntl-Z)の削除は、nkfではできないので、UNIXの一般的な置換コマンドであるtrの削除オプション-dを使って削除するとよいでしょう。0x1aは8進数では32になります。 【表5.6】nkfで同様の変換をおこなうためのオプション オプション 意味 -e 出力コードをEUCにする(半角仮名→全角仮名変換含む) -Lu 行末を0x0a(LF)に変換する 一方、UNIX環境からDOS/Windows環境へファイルを適合させるために必要な変換は少なくとも2つあると思うのですが、wrapnkfではSJIS変換しかしていませんね。これは、CVSが自動的に変換してしまうからのようです。nkfには行末を0x0d,0x0a(CR/LF)に変換する-Lwというオプションがあるのですが、今回は使う必要がありません。 【表5.7】nkfでUNIXにファイルを適合させるためのオプション オプション 意味 -s シフトJISコードを出力する これらの検討から、次のようにwrapnkfを作り直し、wrapnkf2としてみました。自分の環境に合わせたフィルタを各自作られるとよいかと思います。 【図5.27】wrapnkf2 ▼ #! /bin/sh # # wrappper nkf filter for cvs-server/windoze-clients 2 # # Usage: wrapnkf2 kanji_code infile [outfile] # NKF=/usr/bin/nkf # Line Terminator: CR/LF->LF(-Lu), LF->CR/LF(-Lw): No use # Kanji Code: SJIS(-s), EUC(-e) including hankaku->zenkaku TR=/usr/bin/tr # Cntl-Z=\032(0x1a) opt=$1 infile=$2 outfile=$3 if [ ${opt} = "-e" ] ; then ${NKF} -eLu ${infile} | ${TR} -d '\032' > /tmp/unkf-cvs$$ mv -f /tmp/unkf-cvs$$ ${outfile} elif [ ${opt} = "-s" ] ; then ${NKF} -s ${infile} > /tmp/wnkf-cvs$$ mv -f /tmp/wnkf-cvs$$ ${infile} else echo "Usage: wrapnkf2 [-s|-e] infile [outfile]" fi; ▲ ■■■■フィルタを管理しよう このせっかく作ったwrapnkf2をCVSの管理下に置きたいと思います。CVSROOTの下に管理ファイルとして追加してみましょう。そうすれば、バラバラにならなくて済みます。CVSが管理ファイルとしてあらかじめ知っているもの以外のファイルを、管理ファイルと同じように扱うには、checkoutlistファイルに追加する必要がありますね。 【図5.28】checkoutlistファイル ▼ # The "checkoutlist" file is used to support additional version controlled # administrative files in $CVSROOT/CVSROOT, such as template files. # # The first entry on a line is a filename which will be checked out from # the corresponding RCS file in the $CVSROOT/CVSROOT directory. # The remainder of the line is an error message to use if the file cannot # be checked out. # # File format: # # [] # # comment lines begin with '#' wrapnkf2 Kanji Wrapper checkout failed ▲ checkoutlistファイルの書式は1行に一つのファイルを設定する仕組みをとっています。最初にファイル名、次に空白が入り、最後に行末までがエラーメッセージとして扱われます。エラーメッセージはなんらかの理由でこのファイルが取り出せなかったときに出力されるメッセージです。適当で構いません。【図5.28】では、wrapnkf2をエラーメッセージ「Kanji Wrapper checkout failed」とともに設定しています。この設定が終わったら、wrapnkf2をaddし、checkoutlistファイルと一緒にcommitしておきましょう【図5.29】。 【図5.29】wrapnkf2を管理ファイルとして追加する ▼ % cvs add -m "Kanji Wrapper" wrapnkf2 cvs add: scheduling file `wrapnkf2' for addition cvs add: use 'cvs commit' to add this file permanently % cvs commit -m "New administerative file: wrapnkf2" Checking in checkoutlist; /home/cvsroot/CVSROOT/checkoutlist,v <-- checkoutlist new revision: 1.2; previous revision: 1.1 done RCS file: /home/cvsroot/CVSROOT/wrapnkf2,v done Checking in wrapnkf2; /home/cvsroot/CVSROOT/wrapnkf2,v <-- wrapnkf2 initial revision: 1.1 done cvs commit: Rebuilding administrative file database ▲ 管理ファイルが再構築されて、/home/cvsroot/CVSROOT/wrapnkf2ができあがれば成功です。 ■■■■cvswrappersに設定してみよう そして、最後にcvswrapprsに【図5.30】の行を追加します。この図では折り返されていますが、改行は入れないようにしましょう。 【図5.30】cvswrappersに追加する行 ▼ *.tex -f '/home/cvsroot/CVSROOT/wrapnkf2 -s %s' -t '/home/cvsroot/CVSROOT/wrap nkf2 -e %s %s' -s ▲ これをやはりコミットして、動作を確認してください。つまり、test.texというようなファイル名末尾に.texのついたファイルを作って、UNIXとWindowsでやりとりをしてみてください。ちゃんと、変換できていることが確認できましたか? 確認したら、ほかの実際に変換したいファイルについて設定をおこなってください。また、個人ごとに変換したいファイルを変えたい場合は、個人環境設定ファイルの.cvswrappersを用いるのがよいようです。 しかし、pserverでこれを有効にするには、-fオプションで実行ユーザの環境変数を無効にし、inetdが環境変数HOMEを設定しない設定になっている必要があります。上で説明したenvコマンドを利用する設定方法などを試してみてください。ちなみにRedHat Linux 7.xのxinetdでは、envコマンドを利用しなければ、うまくいきませんでした。