一人だけで管理しているサーバの設定ファイルを更新するとき、皆さんはどのように管理しているだろうか。
私は以下のようにしていた。
例えば、httpd.confを2013/8/25に変更しようとするとき。
# vi httpd.conf
# cp -p httpd.conf httpd.conf.20130825
経験のある方はご存じだろうが、長い間これを続けると、ディレクトリが散らかって酷い事になる。
ではバージョン管理を導入すべきか?
でも、一人で管理しているサーバなのに、わざわざsubversionを入れる?それはちょっと。
というのが長らくの悩みであったのだが、実はrcsという簡便なリビジョン管理ツールがあることを知った。今さらではあるが。
しかし、これがまた実に快適であった。
快適すぎて、今ではどこのディレクトリでもRCSディレクトリ(後述)を掘ってしまうくらいになってしまった。
そんなRCSについて以下に記す。
RCSとは。
RCSとはRevision Control System。
きわめて軽量単純なGNU製のリビジョン管理システムである。
一人で使う分には十分(いちおう、ロック機能はあるよ!)。
だいたいのUNIX系OSには最初から入っている。
FreeBSDはベースシステムに入っているので、インストール不要。これはポイント。
もちろんLinuxにも(Redhatの5にあることは確認)
コマンドの使い方を示す。FreeBSD環境下のもの。
Linux向けmanはこちら。
http://linuxjm.sourceforge.jp/html/GNU_rcs/man1/co.1.html
RCSのコマンド
使うコマンドはおおよそ以下のようなもの。
詳しくはman。
co - check out RCS revisions
ci - check in RCS revisions
rlog - print log messages and other information about RCS files
rcsdiff - compare RCS revisions
RCSへの登録
ためしに、/etc/rc.confを、RCSで管理してみる。
最初にやることはRCSに登録すること。
ci(check in)コマンドを使う。
ciにrc.confを渡してやるだけ。
初回は「ファイルの説明を入れろ」と聞いてくるので、“System Setting file"などと入れてみる。
ドット「.」を入れれば完了。
$ cd /etc
$ sudo ci rc.conf
Password:
rc.conf,v <-- rc.conf
enter description, terminated with single '.' or end of file:
NOTE: This is NOT the log message!
>> System Setting File
>> .
initial revision: 1.1
done
最初のバージョンは1.1になる。
初回チェックインの注意
驚くことに、初めてチェックインするとファイルが消える。
代わりと言ってはなんだが、ファイル名末尾に「,v」と付いたファイルが現れる。
$ ls -l rc.conf
ls: rc.conf: No such file or directory
$ ls -l rc.conf*
-r--r--r-- 1 root wheel 353 Aug 25 12:50 rc.conf,v
RCSはそれぞれのファイルを、この「,v」ファイルで管理しているのである。
しかしrc.confが無くなられては困る。
そこでco(check out)コマンドにより、「,v」からrc.confを取り出す。
$ sudo co rc.conf
rc.conf,v --> rc.conf
revision 1.1
done
$ ls -l rc.conf*
-r--r--r-- 1 root wheel 156 Aug 25 12:55 rc.conf
-r--r--r-- 1 root wheel 353 Aug 25 12:50 rc.conf,v
並べてみると「,v」には管理情報が含まれているせいでサイズが少し増えている。
しかしちょっと待て。
「,v」が散らかる→RCSディレクトリで解決
新しいファイルをRCSに登録する都度、「,v」が増えていくのではたまらない。
しかし、そこはさすがに考えられていて、同じディレクトリにRCSというディレクトリがあれば、その下に「,v」を作ってくれる。
さきほど作ったrc.conf,vを消してから試してみる。
$ sudo rm rc.conf,v
$ sudo mkdir RCS
$ sudo ci ./rc.conf
./RCS/rc.conf,v <-- ./rc.conf
(略)
initial revision: 1.1
done
$ ls ./RCS
rc.conf,v
と、ご覧の通り/etc/RCSの下に「,v」が作られる。
こうしておけば「,v」ファイルが散らかって困ることはない。
忘れずにチェックアウト。
RCS/rc.conf,vから取り出されていることが分かる。
$ sudo co rc.conf
RCS/rc.conf,v --> rc.conf
revision 1.1
done
ファイルの更新(チェックアウト)
今度はファイルを更新してみる。
修正したファイルをチェックイン(ci)するだけなのだが、それに先立つチェックアウト(co)の時に考慮すべきことがある。
それはファイルのロック。
単にcoしただけのrc.confのパーミッションを見てみると、読み取り専用(444)になってしまっている(本来は644)。
$ ls -l rc.conf
-r--r--r-- 1 root wheel 156 Aug 25 12:55 rc.conf
なにも無計画にしているわけではない。
「RCSで管理しているファイルを迂闊に書き換えないように」というRCS師匠のありがたい配慮である。
これを避けるには、ファイルのロックをしてからチェックアウトをすればよい。
coの際に-lオプション(lock)を与えるだけ。
$ sudo co -l rc.conf
Password:
RCS/rc.conf,v --> rc.conf
revision 1.1 (locked)
done
$ ls -l ./rc.conf
-rw-r--r-- 1 root wheel 156 Aug 25 12:56 ./rc.conf
(locked)という表示が増えている。
また、パーミッションも644になっている。
これでファイル変更の準備ができた。
ファイルの更新(チェックイン)
修正が済んだらチェックイン。
チェックアウトの時と同じように、ロックの考慮が必要。
端的に言えばロックを解除する。
ciの際に-uオプション(unlock)を与える。
$ sudo ci -u ./rc.conf
./RCS/rc.conf,v <-- ./rc.conf
new revision: 1.2; previous revision: 1.1
enter log message, terminated with single '.' or end of file:
>> disable sendmail on boot
>> .
done
$
log message、つまり修正内容の記入が求められるので書き入れたのちドット「.」で終了。
そしてロック解除したために、再びファイルのバーミッションが444に戻っている。
$ ls -l ./rc.conf
-r--r--r-- 1 root wheel 283 Aug 25 19:29 ./rc.conf
履歴の確認
RCSで管理しているファイルに対しrlogを発行すると履歴が表示される。
$ rlog ./rc.conf
RCS file: ./RCS/rc.conf,v
Working file: ./rc.conf
head: 1.2
branch:
locks: strict
access list:
symbolic names:
keyword substitution: kv
total revisions: 2; selected revisions: 2
description:
System configuration file
----------------------------
revision 1.2
date: 2013/08/25 10:29:49; author: root; state: Exp; lines: +6 -0
disable sendmail on boot
----------------------------
revision 1.1
date: 2013/08/25 04:07:09; author: root; state: Exp;
Initial revision
----------------------------
=============================================================================
revisoin 1.2では9行追加されていることを示している。
デフォルトではタイムスタンプがUTC。
これは分かりにくいので、ローカルタイムで表示する。
そのためには-zLTを与える。
$ rlog -zLT ./rc.conf
RCS file: ./RCS/rc.conf,v
Working file: ./rc.conf
head: 1.2
branch:
locks: strict
access list:
symbolic names:
keyword substitution: kv
total revisions: 2; selected revisions: 2
description:
System setting file
----------------------------
revision 1.2
date: 2013-08-25 19:29:49+09; author: root; state: Exp; lines: +6 -0
disable sendmail on boot
----------------------------
revision 1.1
date: 2013-08-25 13:07:09+09; author: root; state: Exp;
Initial revision
----------------------------
=============================================================================
差分の確認
二つのバージョン間の差分を確認するには、rcsdiffを使う。
$ rcsdiff -r1.1 -r1.2 ./rc.conf
===================================================================
RCS file: ./RCS/rc.conf,v
retrieving revision 1.1
retrieving revision 1.2
diff -r1.1 -r1.2
6a7,12
>
> # kill sendmail
> sendmail_enable="NO"
> sendmail_submit_enable="NO"
> sendmail_outbound_enable="NO"
> sendmail_msp_queue_enable="NO"
特定のバージョンを取り出す。
coに-rオプションでバージョンナンバを指定する。
1.1を取り出したいなら-r1.1。
$ sudo co -r1.1 rc.conf
RCS/rc.conf,v --> rc.conf
revision 1.1
done
しかしこれでは手元にあるファイルが上書きされる。
都合が悪い場合には-pオプションを使う。
-pオプションは結果を標準出力に表示させるもの。
$ sudo co -p -r1.1 rc.conf > /tmp/rc.conf
RCS/rc.conf,v --> standard output
revision 1.1
ident文字列の埋め込み
ファイルを特定しやすくするための仕組みがident文字列。
ある文字列を埋め込んでおくと、RCSが自動的に置換・更新をしてくれる。
実際に見てもらった方が早い。
rc.confに埋め込んでみる。
ident文字列には何種類かあるが、ここでは「$Id$」を使う。
しかし、$Id$といきなり書いてはいけない。コメントとして埋め込もう。
すなわち、#のあとに続ける。
(同様に、たとえばxmlなら”<!-“と”->“の間、というようにフォーマットに合わせたコメント文に埋め込むとよい)
rc.confの例
#$Id$
hostname="hogehoge"
keymap="jp.106.kbd"
ifconfig_em0="DHCP"
sshd_enable="YES"
これをチェックインすると、自動的に以下のように変換してくれる。
$ head -1 /etc/rc.conf
#$Id: rc.conf,v 1.2 2013/08/24 10:52:27 root Exp $
これは便利である。
実はこの文字列、よく見かけたのだが、やっとその秘密が分かった。
しかしタイムスタンプはUTCである。
チェックインのときに-zLTと指定すればローカルタイムで置換してくれる。
$ sudo ci -u -zLT ./rc.conf
./RCS/rc.conf,v <-- ./rc.conf
new revision: 1.4; previous revision: 1.3
enter log message, terminated with single '.' or end of file:
>> update timestamp from UTC to LT
>> .
done
$ head -1 ./rc.conf
#$Id: rc.conf,v 1.4 2013-08-24 20:18:36+09 root Exp $
ident文字列のちょっとしたノウハウ
ident文字列の場所はどこでもよい。
しかし、1行目か2行目がよいでしょう。
ident文字列はファイルのIDとして埋め込んでいる。
IDの場所がバージョンごとに違うと、のちのち差分を確認するときに見にくくなってしまうから。