2011年11月30日水曜日

RHEL6 系で qemu-kvm バイナリを CPU エミュレーション・モードで使う

お疲れ様です、サイオス 那賀です。突然ですが、今どきの仮想マシンにの実現方法としては、おおざっぱに以下の 3 種類があります。

CPU エミュレーション (インタプリタや、全部バイナリ変換 (Binary Translation))
QEMU, Bochs など。超重いが、他 CPU の命令実行もできて柔軟。実装が大変
トラップ実行 (Trap and Execute。TAE とでも?) + 部分バイナリ変換
(Workstation など、昔ながらの) VMware (実は ESXi でもできるんですが), (昔ながらの) VirtualBox, KQEMU (きわめて残念なことに開発終了) など。ハードウェア支援が不要。CPU 命令をネイティブで走らせるので、そこそこ速い。実装が大変
ハードウェア支援仮想化 (Hardware-Assisted Virtualization, HAV)
QEMU virtualizer (QEMU-KVM), Xen-HVM, HAV モードの VMware (ESXi とか), HAV モードの VirtualBox など。intel VT-xAMD-V が必要。速い、と言われている。実装が(比較的に)簡単

# 何かと面倒な準仮想化 (Para-virtualization, PV) や、OS 仮想化のコンテナ方式については脇に置きます

一般に、前者ほど遅くて後者ほど速いです(初期の VT-x は root, non-root 移行のコストが高くて、むしろ TAE の方が速かったりもしたらしいですが)。最近の実用環境では HAV が主流なのですが、HAV 方式の欠点として、VM 環境上では VM が動かせないことがあります。

# AMD-V だと、VM のスタックができるというウワサを聞きましたが、よく知りません →「Running OpenStack under VirtualBox « System Administration and Architecture Blog

何がしたいかと言うと、EucalyptusOpenStack のような IaaS プラットフォームをお手軽にテストしたいのですが、実マシンをそうそうゴロゴロと用意できない時に、VM 上でテストをできるようにしたいのです。しかし、それらのプロットフォームは、最近の流行からして、開発のプライマリに据えているハイパーバイザが KVM なのです。

これらは、実装的には libvirt 配下で VM ハイパーバイザを動かすようになっているので、理屈上は Xen や VirtualBox でも動きそうなものですが、KVM が開発のプライマリなので、何かと動きません。そもそも、RHEL6 だと Xen の Dom0 も動きませんし、RHEL5 だと Python その他が古すぎて IaaS プラットフォームが動かなかったりもします。

そこで、KVM も動作には QEMU-KVM を使っているので、かわりに QEMU を使うと結構動きます。しかし残念なことに、以前はあった KQEMU による TAE 方式は開発が止まってしまったので、泣く泣く QEMU の CPU エミュレーションモードを使います。

RHEL6 に入っている "qemu-kvm" というコマンドは、実態としては "qemu-system-x86_64" であり、ビルド時に名前を変えているだけです。このバイナリは、KVM のオプションをつければ KVM を利用した HAV 方式で動きますが、KVM を切っておけば、CPU エミュレーションでも動きます。KVM virtualizer 推しのために、emulator をわざと使えなくしているようです。

libvirt-0.8.7/src/qemu/qemu_capabilities.c:

static int
qemuCapsInitGuest(virCapsPtr caps,
                  virCapsPtr old_caps,
                  const char *hostmachine,
                  const struct qemu_arch_info *info,
                  int hvm)
{
  ...
  if (STREQ(info->arch, hostmachine) ||
   (STREQ(hostmachine, "x86_64") && STREQ(info->arch, "i686"))) {
    if (access("/dev/kvm", F_OK) == 0) {
      ...
      const char *const kvmbins[] =
       { "/usr/libexec/qemu-kvm", /* RHEL */
         "qemu-kvm", /* Fedora */
         "kvm" }; /* Upstream .spec */
      ...
    }
    if (access("/dev/kqemu", F_OK) == 0)
      haskqemu = 1;
  }

上記のように、libvirt は、コマンドのパスとモジュールのロード状況に基づいて、その環境上で利用可能なハイパーバイザーを判断しています。よって、RHEL6 でもリンクを張るだけで、libvirt 経由で QEMU のエミュレーションモードが使えるようになります。

# ln -sf /usr/libexec/qemu-kvm /usr/bin/qemu-system-x86_64

これで、VM 上で QEMU の完全仮想化エミュレーションが動くようになります。Virt-Manager 上での表示としては、以下のようになります。

「Hypervisor」「Architecture」
KVM 有効の virtualizer「KVM」「x86_64」
QEMU emulator「qemu」「x86_64」

以下は、Windows 版の VMware Workstation 上の Scientific Linux 6 (x64) 上の Virt-Manager 上で Scientific Linux (IA32) を動かした例です。

もちろん、とっても遅いです。しかし、動かないよりはマシですので、テスト用に使っています。

では。

2011年11月29日火曜日

なぜオンライン EXT3 の LVM2 スナップショット & バックアップは問題なく動くのか?

お疲れ様です、サイオス 那賀です。新書本風のタイトルにしてみました。

最初に、私の自宅サーバの、えらく大雑把なバックアップを紹介しようと思います。日に一回、ルート直下のスナップショットを、まるごと別のハードディスクに rsync で増分バックアップしています。システムは以下のようにマウントされています。/ 直下が LVM であり、EXT4 でマウントされています。

$ mount | grep /dev/mapper
/dev/mapper/vg_main-lv_main on / type ext4 (rw,errors=remount-ro)
/dev/mapper/vg_sub-lv_sub on /sub type ext4 (rw)

以下は、1 日 1 回実行されるバックアップスクリプトです。LVM スナップショットをリードオンリーでマウントし、rsync でコピーするだけの簡単なものです。

$ cat /etc/cron.daily/backup-snapshot
#!/bin/sh

mntpnt=/mnt/tmp

# /vm/ は大きいので、日曜日にだけバックアップ
foptvm=
# From Sunday, 0-indexed
test $(date +%w) != 0 && foptvm="$foptvm --exclude /vm/"

mkdir -p /sub/_
lvcreate --size 30G --snapshot --name lv_snap /dev/vg_main/lv_main
mount -o ro /dev/vg_main/lv_snap $mntpnt
if test -d $mntpnt/proc
then
  rsync -avr --delete $foptvm $mntpnt/ /sub/_
fi
umount $mntpnt
lvremove -f /dev/vg_main/lv_snap

当初は、DB ごとに個人データごとにと、個別にバックアップをとっていたのですが、サーバの用途が増えてきたためだんだん面倒くさくなってきてしまい、このような丸ごとバックアップに落ち着きました。問題なく動いていたので、これで正しいのだろうと思っていたのですが、ふとログを見ると、以下のようなメッセージが出ていました。

$ grep EXT4 /var/log/messages
Nov XX 06:25:03 queen kernel: [10216804.075357] EXT4-fs (dm-3): orphan cleanup on readonly fs
Nov XX 06:25:03 queen kernel: [10216804.151685] EXT4-fs (dm-3): 43 orphan inodes deleted
Nov XX 06:25:03 queen kernel: [10216804.151689] EXT4-fs (dm-3): recovery complete
Nov XX 06:25:04 queen kernel: [10216804.249053] EXT4-fs (dm-3): mounted filesystem with ordered data mode. Opts: (null)
Nov YY 06:25:03 queen kernel: [10303060.217676] EXT4-fs (dm-3): orphan cleanup on readonly fs
Nov YY 06:25:03 queen kernel: [10303060.542436] EXT4-fs (dm-3): 45 orphan inodes deleted
Nov YY 06:25:03 queen kernel: [10303060.542441] EXT4-fs (dm-3): recovery complete
Nov YY 06:25:03 queen kernel: [10303060.648882] EXT4-fs (dm-3): mounted filesystem with ordered data mode. Opts: (null)
Nov ZZ 06:25:02 queen kernel: [10389317.017146] EXT4-fs (dm-3): orphan cleanup on readonly fs
Nov ZZ 06:25:02 queen kernel: [10389317.117018] EXT4-fs (dm-3): 45 orphan inodes deleted
Nov ZZ 06:25:02 queen kernel: [10389317.117023] EXT4-fs (dm-3): recovery complete
Nov ZZ 06:25:03 queen kernel: [10389317.215482] EXT4-fs (dm-3): mounted filesystem with ordered data mode. Opts: (null)

特に気になるのが「~ orphan inodes deleted」です。リードオンリーでマウントしているはずなのに、EXT4 のクリーンアップが動いて、ファイルシステムに変更を加えているように見えます。この分だと、ジャーナルのリプレイもしているのではないでしょうか? むしろジャーナルのリプレイができないとなると、マウントしたままの EXT4 のブロックデバイスイメージから取っているスナップショットですので、ファイルシステムには不整合が生じているのでは? そもそも、LVM のスナップショットって書きこめるの?

と、疑問が出てきてしまったので、検証してみました。まずは、「LVM のスナップショットに書き込めるのか?」から。

root@queen:~# lvcreate --size 30G --snapshot --name lv_snap \
 /dev/vg_main/lv_main
  Logical volume "lv_snap" created
root@queen:~# mount -o rw /dev/vg_main/lv_main /mnt/tmp
root@queen:~# ls -l /mnt/tmp/hoge
ls: cannot access /mnt/tmp/hoge: No such file or directory
root@queen:~# echo hoge > /mnt/tmp/hoge
root@queen:~# cat /mnt/tmp/hoge
hoge
root@queen:~# umount /mnt/tmp/
root@queen:~# lvremove -f /dev/vg_main/lv_snap
  Logical volume "lv_snap" successfully removed

余裕で書き込めますね。知らなかった…。「LVM HOWTO」の「Snapshots」の項に、以下のようにあります。

In LVM2, snapshots are read/write by default. Read/write snapshots work like read-only snapshots, with the additional feature that if data is written to the snapshot, that block is marked in the exception table as used, and never gets copied from the original volume.

LVM2 になってからは、スナップショットの差分領域は、スナップショット元からの差分を保持すると同時に、スナップショットへの書き込み差分も保持するようになっているそうです。静的なスナップショットというよりも、動的に書き込める、揮発的なブランチのようなものですね。

さて、LVM スナップショットに書き込めることは分かったので、次は、リードオンリー・マウントでも EXT4 がマウント時にファイルシステムの修復を行うかどうか、です。

余談なのですが、最近の Linux は I/O フリーズの機能を持っています。ファイルシステムを一貫性のある状態に移行させてから一時「凍結」し、バックアップやコピーをとるための機能です。これを使えば、以下のようにきれいなスナップショットがとれます。

  • ioctl(2) に FIFREEZE で、I/O を止め、一時的にファイルシステムを一貫性のある状態に保つ
  • LVM でブロックデバイスのスナップショットをとる
  • FITHAW で、フリーズを解除
  • スナップショットをマウントし、ゆっくりと rsync ででもコピーをとる
  • アンマウントして、スナップショットを開放

しかし残念ながら、今の LVM などでは、この機能を使っていません…か? FIFREEZE 等の呼び出しがないことから、てっきり使っていないと思っていたのですが、RHEL6 などで FIFREEZE/FITHAW の ioctl() を発行するためのコマンド fsfreeze(8) の man を参照すると、以下のように書かれています。

fsfreeze is unnecessary for device-mapper devices. The device-mapper (and LVM) automatically freezes filesystem on the device when a snap-shot creation is requested. For more details see the dmsetup(8) manpage.

LVM2 のコードを見てみると(かなり読みづらいコードなのですが)、lvcreate(8) でスナップショットを作成すると、device mapper の「ブロックデバイスに対して」、DM_DEV_SUSPEND_CMD で ioctl() を呼んでいます (これは、drivers/md/dm-ioctl.c まわりのコードです。対して、ファイルシステムへのコードは linux/fs/ioctl.c:ioctl_fsfreeze() にあり、FIFREEZE での ioctl() が、「ファイルシステム上のノードに対して」発行されます)。とはいえ、結果的には、両者とも同一のスーパーブロックに対して freeze_bdev() を実行することになります。ブロックデバイスのくせして、自分の上に載っているファイルシステムにまで干渉するとは、何だか妙な感じがしますが、理にかなってはいます。

よって、LVM2 でスナップショットを取る前には、一瞬 I/O を停止して、ファイルシステムを整合性を保った状態まで持って行ってからスナップショットを作成しています。

以上でスナップショットについては解決したのですが、では、異常終了時の EXT3 はどうなんでしょう。結論から言うと、「[RFC, PATCH 0/6] ext3: do not modify data on-disk when mounting read-o」や「'Add a norecovery option to ext3/4?' - MARC」を見ると分かるように、実は「-o ro」オプションをつけてマウントしても、EXT3/EXT4 は、可能であれば(デバイスが書き込み可能であれば)ジャーナルのリプレイと orphan inode の切り落としをしてしまいます。ソース中では "really_read_only" のフラグで分岐しています。

linux-2.6.32/fs/ext4/super.c:

static int ext4_load_journal(struct super_block *sb,
                             struct ext4_super_block *es,
                             unsigned long journal_devnum)
{
    ...
    int really_read_only;
    ...
    really_read_only = bdev_read_only(sb->s_bdev);
    ...
    if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER)) {
        if (sb->s_flags & MS_RDONLY) {
            ext4_msg(sb, KERN_INFO, "INFO: recovery "
                "required on readonly filesystem");
            if (really_read_only) {
                ext4_msg(sb, KERN_ERR, "write access "
                    "unavailable, cannot proceed");
                return -EROFS;
            }
            ext4_msg(sb, KERN_INFO, "write access will "
               "be enabled during recovery");
        }
    }
    ...
}

以上をまとめますと、

  • LVM2 では、元 LV のダーティバッファはスナップショットにも反映される
  • LVM2 のスナップショットには、書き込みができる
  • スナップショットはブロックデバイスでありながら、その上層のファイルシステムと示し合わせて、一貫性のある状態でのスナップショットを取ってくれる
  • EXT3/EXT4 の "-o ro" マウントは、(journal リプレイと) orphan inode 切り落としをする

以上から、EXT3/EXT4 の、ある瞬間のスナップショットを LVM2 でとって、それをリードオンリーマウントしてコピーをとっても、一貫性の点では問題はないということですね。

やれやれ、ZFS や btrfs のような、シャドウコピーで手軽にファイルシステムレベルでスナップショットを利用できるようになれば、LVM を事前に用意する必要もないので、はるかに話は簡単になるんですが。早くデフォルトにならないかなぁ。

ではまた。

CentOS 6.0 でインストール直後にネットワークを有効にする方法

サイオステクノロジー 金田です。

CentOS 6.0 の GUI インストールで、CentOS 5 系と同じように設定変更せず先に進めると、インストール後のネットワークが有効にならずに困ったことがあります。

インストールしてしまったら、/etc/sysconfig/network-scripts/ifcfg-eth0 を編集するか、GUI のメニュー 「システム」→「設定」→「ネットワーク接続」から有効化すればいいのですが、できればインストール時に有効化したいですよね?今回はその方法を紹介します。

CentOS 6.0 のインストール中にホスト名を設定する画面(画像1)が表示されたら「ネットワークの設定」ボタンをクリックします。

画像1 CentOS 6.0 インストール時ホスト名設定画面

実は、CentOS 5 系ではこのタイミングでネットワークが有効になっている(画像2)だけなんですね。

画像2 CentOS 5系のインストール時ホスト名設定画面

話を CentOS 6.0 に戻します。
次に「ネットワーク接続」のウィンドウ(画像3)の「有線」タブで「System eth0」を選択して「編集...」ボタンをクリックします。

画像3 「ネットワーク接続」ウィンドウ
「System eth0 の編集」ウィンドウ(画像4)で「自動接続する」のチェックボックスをチェックすれば、インストール後にネットワークが有効になります。

画像4 「System eth0」ウィンドウ

RHEL6 や Scientific Linux 6 でも同じ方法で変更できます。

2011年11月28日月曜日

PostgreSQL 死活監視のタイムアウト

お疲れぎみです、サイオス 那賀です。

スクリプト等から PostgreSQL のプロセスが正しく動作しているかどうかを監視するための方法としては、pg_ctl コマンドを使ってのチェックと、実際にポートにアクセスしてのチェックがあると思います。

まずはプロセスの確認です。pg_ctl コマンドの "status" サブコマンドで、ローカルで動作している PostgreSQL のプロセスの状態を取ることができます。

$ /usr/local/pgsql/bin/pg_ctl -D ~/pgdata-main/ status
pg_ctl: postmaster is running (PID: 10532)
Command line was:
/usr/lib/postgresql/8.4/bin/postgres "-D" "/home/knaka/pgdata-main"

"-D" オプションで指定したデータディレクトリ下には "postmaster.pid" ファイルがあり、内容は、外部からのコネクションを受け付けている Postmaster プロセスのプロセス番号 (PID) です。この PID に対応するプロセスが動作しているどうかの結果を返します。

このコマンドがブロックしてしまうことはないのでしょうか? 少しソースも見てみましょう。Postmaster の死活を見ているのは、下記の部分です。src/bin/pg_ctl/pg_ctl.c です。

static bool
postmaster_is_alive(pid_t pid)
{
  ...
  if (kill(pid, 0) == 0)
    return true;
  ...
}

kill(2) にシグナル番号 0 を投げるというのはどういう意味でしたっけ? man には以下のようにあります。

If sig is 0, then no signal is sent, but error checking is still per-formed; this can be used to check for the existence of a process ID orprocess group ID.

単にプロセスが存在しているかどうかしか見ていませんが、これがブロックすることはなさそうなので、DB の状態に拠らず安心して呼べますね。しかしこれでは、プロセスはあるけれど実際にはサービスが行われていなかった場合を検出できません。

そこで、ネットワークのポート (TCP/IP なりドメインソケットなりの) に接続して死活監視を行います (パスワードを訊かれないよう、パスワードファイルなりサービスファイルなりは事前に設定しておいてください)。

$ psql -h localhost -p 5433 -U admin template1 -l
                          List of databases
   Name    | Owner | Encoding | Collation | Ctype | Access privileges
-----------+-------+----------+-----------+-------+-------------------
 eucdb     | admin | EUC_JP   | C         | C     |
 main      | admin | UTF8     | C         | C     |
 postgres  | knaka | UTF8     | C         | C     |
 template0 | knaka | UTF8     | C         | C     | =c/knaka
(中略)
$ echo $?
0 

# なおここで、"postgres" データベースに接続してチェックするのはやめましょう。世の中には "postgres" データベースを持たない PostgreSQL データベースがあります。"template1" が無いことはありません。

しかしながら、もしポートを開いたまま死んでいる PostgreSQL へ不用意に接続して状態を確認してしまうと、いつまでも待ってしまいます。netcat コマンドで listen ポートを開いて試してみましょう。

$ nc -l 15432
(待ち...)

別のコンソールから。

$ psql -h localhost -p 15432 -U postgres postgres
(待ち...)

はい、返ってきません。もし一定時間ごとに死活監視のコマンドを発行するようにしていたら大変です。プロセスは増え続け、いずれリソースを食い尽くします。

そんな時、たとえば SSH でリモートのコマンドを叩くような状態監視であれば、タイムアウトのパラメータを渡すことで対処します。

$ nc -l 10022

$ ssh -p 10022 localhost
これだと戻りませんが。
$ ssh -o "ConnectTimeout=5" -p 10022 localhost
(5 秒経過…)
Connection timed out during banner exchange
$ echo $?
255
$ 

"ConnectionTimeout" パラメータを渡すことで、ちゃんとエラーを返すようになりました。

一方、psql コマンドのドキュメントにはそういうオプションが見当たりません。しかし psql コマンドは、実際のデータベースへの接続には libpq ライブラリを用いており、タイムアウトの設定はそちらにあります。libpq が理解する環境変数を見てみますと、"PGCONNECT_TIMEOUT=~" というのがありますね。試してみましょう。

$ PGCONNECT_TIMEOUT=5 psql -h localhost -p 15432 -U postgres postgres
(5 秒経過…)
psql: timeout expired
$ echo $?
2

めでたくタイムアウトし、エラーのリターンコードを返すようになりました。

では

2011年11月25日金曜日

ソースの入手と再ビルド ~ Ubuntu 編

お疲れ様です、サイオス 那賀です。

先日のエントリで、RPM 系ディストリビューションにおけるソースの入手とビルド方法には触れましたので、今度は簡単に、Debian 系ということで Ubuntu 上でのビルドをしてみます。なお、私も RPM を主戦場としておりまして、Debian 系の習熟度は普通のシスアド程度なのですが、やはりイザという時にソースの入手やビルド程度できねばなるまいと思いまして、あえてメモ書き程度に記しておきます。

まずは、パッケージビルドをするためのツールを含む "dpkg-dev" をインストールします。そして、後で Bash のビルドを試しますので、依存パッケージをインストールしておきます。

root@queen:~# aptitude install dpkg-dev
root@queen:~# aptitude build-dep bash

以降は一般ユーザで行います。apt-get で source を入手できます。

nonpriv@queen:~$ mkdir -p ~/deb/
nonpriv@queen:~$ cd ~/deb/
nonpriv@queen:~/deb$ apt-get source bash
(中略)
nonpriv@queen:~/deb$ ls -l
total 4016
drwxr-xr-x 3 nonpriv nonpriv    4096 2011-XX-XX 14:36 bash-4.1
-rw-r--r-- 1 nonpriv nonpriv   87125 2010-08-11 05:05 bash_4.1-2ubuntu4.diff.gz
-rw-r--r-- 1 nonpriv nonpriv    1296 2010-08-11 05:05 bash_4.1-2ubuntu4.dsc
-rw-r--r-- 1 nonpriv nonpriv 4013077 2010-01-05 04:10 bash_4.1.orig.tar.gz

RPM のビルドが手続き的なのに対して、ダウンロードしてきた "bash-4.1/" ディレクトリの中を見て分かるとおり、Debian のビルドは、元のビルドシステムを生かしつつ、そこへラッパーを被せているようなノリがあります。うまく言えないけれど、そんな感じです。

ここで deb パッケージを作成するだけであれば、下記で充分です。

nonpriv@queen:~/deb/bash-4.1$ dpkg-buildpackage

右記をひととおり読めば、誰でも deb ソースパッケージの操作、作成はできるようになると思います → 「Debian 新メンテナーガイド」。SPEC ファイル書き方講座の決定版とも言える「Maximum RPM」が 10 年以上もそのままなのに比べると、Debian プロジェクトはきちんとしているなぁと思わざるを得ません。

2011年11月24日木曜日

肥大化した個人利用の Git ワークを縮小する

お世話になります、サイオス 那賀です。

CVS や Subversion 等の集中型バージョン管理と違い、Git のような分散型のバージョン管理では、明確な「ワーク」というものはありません(ワークではないレポジトリはありますが)。そのため、clone された各ワークは、それまでの変更履歴を全て抱えています。多人数での開発であれば、過去の、どの履歴をいつ参照する必要が生じるとも分からないので、ヒストリを勝手に消したら叱られるでしょうが、個人利用では、どう考えても今後必要にならないヒストリは、ディスクの肥やしでしかありません。途中の変更履歴を削除し、ワークのサイズを小さくする方法を把握しておくことは有益かと思います。

# 私的な事情としては、ワークを Dropbox 上に置いて Linux と Windows で共用しているため、無駄に大きくなられると、ネットストレージの容量を圧迫して困るのです

まずは、もしまだ git を使ったことのない環境であれば、コミット時のユーザ名とメールアドレスを設定しておきます。

[nonpriv@sl6kdev ~]$ git config --global user.name "Foo Bar"
[nonpriv@sl6kdev ~]$ git config --global user.email "foobar@example.com"

空のレポジトリを作成します。初期サイズは、100KB ほどのようです。

[nonpriv@sl6kdev ~]$ mkdir ~/repos/
[nonpriv@sl6kdev ~]$ git init --bare ~/repos/
Initialized empty Git repository in /home/nonpriv/repos/.git/
[nonpriv@sl6kdev ~]$ du -hs ~/repos/
100K    /home/nonpriv/repos/

clone でワークを作成します。サイズは 104KB ほどです。

[nonpriv@sl6kdev ~]$ git clone file:///home/nonpriv/repos/ ~/work/
Initialized empty Git repository in /home/nonpriv/work/.git/
warning: You appear to have cloned an empty repository.
[nonpriv@sl6kdev ~]$ cd work/
[nonpriv@sl6kdev work]$ du -hs .
104K    .

ワークにおいて、特に何の変哲もない最初のコミットと、レポジトリへの push を行います。

[nonpriv@sl6kdev work]$ echo first > hoge.txt
[nonpriv@sl6kdev work]$ git add hoge.txt
[nonpriv@sl6kdev work]$ git commit -m "First commit"
[master (root-commit) f3241b3] First commit
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 hoge.txt
[nonpriv@sl6kdev work]$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 213 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To file:///home/nonpriv/repos/
 * [new branch]      master -> master

次に、うっかり巨大な内容 (10MB ほど) をコミット、push してしまいました。

[nonpriv@sl6kdev work]$ dd if=/dev/urandom of=hoge.txt bs=10M count=1
[nonpriv@sl6kdev work]$ git add hoge.txt
[nonpriv@sl6kdev work]$ git commit -m "Second commit contains big data"
[master cbd23c4] Second commit contains big data
 1 files changed, 0 insertions(+), 0 deletions(-)
[nonpriv@sl6kdev work]$ git push
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 10.00 MiB, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To file:///home/nonpriv/repos/
   f3241b3..cbd23c4  master -> master

仕方が無いので、巨大なコミットを消しにかかります。

[nonpriv@sl6kdev work]$ echo third > hoge.txt
[nonpriv@sl6kdev work]$ git add hoge.txt
[nonpriv@sl6kdev work]$ git commit -m "Third commit removes it"
[master 56770a2] Third commit removes it
 1 files changed, 1 insertions(+), 40970 deletions(-)
 rewrite hoge.txt (100%)
[nonpriv@sl6kdev work]$ git push
Counting objects: 5, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (1/1), done.
Writing objects: 100% (3/3), 253 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To file:///home/nonpriv/repos/
   cbd23c4..56770a2  master -> master

ここで CVS や Subversion であれば、ワークのサイズは小さくもなりましょうが、Git ではワークもレポジトリなので、レポジトリ内に過去の履歴が残っており、実サイズは小さくなりません。

[nonpriv@sl6kdev work]$ cd ~
[nonpriv@sl6kdev ~]$ git clone file:///home/nonpriv/repos/ ~/work2/
Initialized empty Git repository in /home/nonpriv/work2/.git/
remote: Counting objects: 9, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 9 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (9/9), 10.00 MiB, done.
[nonpriv@sl6kdev ~]$ du -hs ~/work2
11M     /home/nonpriv/work2

そこで、rebase コマンドの squash で、ヒストリ上から、大きなコミットを無かったことにします。

[nonpriv@sl6kdev ~]$ cd ~/work/
[nonpriv@sl6kdev work]$ git log
commit 56770a2af0d3a9d636f38993eb12d517bdf9949f
Author: Foo Bar <foobar@example.com>
Date:   XXX Nov XX 11:04:06 2011 +0900

    Third commit removes it

commit cbd23c48a7d24cba52bd1e6ff795ea06f4d7d710
Author: Foo Bar <foobar@example.com>
Date:   XXX Nov XX 11:03:19 2011 +0900

    Second commit contains big data

commit f3241b3584cbd2e9ede54bcb6bd7f8363e7615c3
Author: Foo Bar <foobar@example.com>
Date:   XXX Nov XX 11:02:10 2011 +0900

    First commit
[nonpriv@sl6kdev work]$ git rebase --interactive f3241b3584cbd2e9ede54bcb6bd7f8363e7615c3

巨大な内容を削除するためのコミット (ここでは "Third commit") を squash し、その前の "Second commit" と合わせて 1 つにしてしまいます。これで、論理的には、巨大な内容のコミットは無かった事になります。

pick cbd23c4 Second commit contains big data
squash 56770a2 Third commit removes it

ヒストリを破壊するこの変更は、当然リモートリポジトリに対して全く fast-forward ではないので、"--force" で push します。

[nonpriv@sl6kdev work]$ git log
commit f6ed91fc820e974f1221fe621e34b17fbd6e317d
Author: Foo Bar <foobar@example.com>
Date:   XXX Nov XX 11:03:19 2011 +0900

    Second commit contains big data

    Third commit removes it

commit f3241b3584cbd2e9ede54bcb6bd7f8363e7615c3
Author: Foo Bar <foobar@example.com>
Date:   XXX Nov XX 11:02:10 2011 +0900

    First commit
[nonpriv@sl6kdev work]$ git push --force
Counting objects: 5, done.
Writing objects: 100% (3/3), 278 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To file:///home/nonpriv/repos/
 + 56770a2...f6ed91f master -> master (forced update)

さて、小さくなったでしょうか。

[nonpriv@sl6kdev work]$ cd ~
[nonpriv@sl6kdev ~]$ git clone file:///home/nonpriv/repos/ ~/work3/
Initialized empty Git repository in /home/nonpriv/work3/.git/
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), 459 bytes, done.
[nonpriv@sl6kdev ~]$ du -hs ~/work3/
160K    /home/nonpriv/work3

だいぶ小さくなりました。良いようです。

non-fast-forward を "--force" で push してしまったので、それ以前に clone されていた別のワークは危険です。消しておきましょう。

[nonpriv@sl6kdev ~]$ rm -fr ~/work2/

以上です。

注意: squash した結果を push したレポジトリ (上記の例では ~/repos/) には、実はまだ squash で潰されたはずの内容が残っています。あまり追求していないので、実体として何が残っているのかはよく知りません。

[nonpriv@sl6kdev ~]$ du -hs ~/repos/
11M     /home/nonpriv/repos/

そしてここから clone する際、ローカルパスの URL 形式 ("file://~") ではなくローカルのパスを指定して clone してしまうと、Git はローカルのコピーやハードリンクを用いてワークを作成してしまうため、小さくなりません。

[nonpriv@sl6kdev ~]$ git clone ~/repos/ ~/work4/
Initialized empty Git repository in /home/nonpriv/work4/.git/
[nonpriv@sl6kdev ~]$ du -hs ~/work4/
11M     /home/nonpriv/work4/

レポジトリを clone しなおして、~/repos/ を入れかえておくのも手かと思います。

[nonpriv@sl6kdev ~]$ git clone --mirror file:///home/nonpriv/repos/ ~/repos-new/
Initialized empty Git repository in /home/nonpriv/repos-new/
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (6/6), done.
[nonpriv@sl6kdev ~]$ rm -fr ~/repos/
[nonpriv@sl6kdev ~]$ mv ~/repos-new/ ~/repos/

git-clone(1) のヘルプには「ローカルパス指定と file://~ とでは、大差ないよ」とか書けれていますが、実のところは違います。特に事情がなければ、常に "file://~" なりネットワーク接続指定なりを用いる方が安全だと思います。ソースで言うと、builtin/clone.c の cmd_clone() における、"clone_local(path, git_dir)" と "transport_get_remote_refs(transport)" との is_local フラグによる分岐を参照してください。

もっとも、ストレージリソースが潤沢にあるならば、どっちでもいいんですけどね。

注意 2: ブランチを切っているようであれば、ワーク側でひととおり checkout しておいてやる必要もあります。参考 → 「Why is my git repository so big? - Stack Overflow」。

では。

2011年11月22日火曜日

RPM 版 Tomcat のマルチインスタンス化

初めての投稿になります。サイオスの鎌田です。

RHEL6 からは、提供される Tomcat のバージョンが 6.x 系となり、OpenJDK との組み合わせで今後利用が増えてくるのではないでしょうか。社内向けのツールなど、簡単な Web アプリケーションであれば RHEL6 上で動作させ、運用していくことも十分に考えられるかと思います。

しかし、RPM 版 Tomcat を用いる上で、こういった問題を抱えてはいないでしょうか。Web アプリケーション同士の相性により、1つの Tomcat インスタンス上で同時に動作させると問題が生じるため、仕方なくコミュニティ版の Tomcat で環境を構築するといった問題です。代表的な例として、Atlassian 社製のエンタープライズ Wiki アプリケーションである Confluence と、同社の ITS である JIRA は、それぞれを 1つの Tomcat インスタンス上で動作させることはサポート対象外としています。

実は、RPM 版 Tomcat でマルチインスタンス化させることは可能なのです。元々の Tomcat の機能を使うだけなのですが、RPM 版 Tomcat では init スクリプトでマルチインスタンスを管理できるように考慮されて作られています。以下、その手順を述べます。

2011年11月17日木曜日

PostgreSQL を SNMP で監視する

お世話になっております、サイオス 那賀です。

pgsnmpd は、RFC1697 (RDBMS-MIB) に準拠した、PostgreSQL 用の SNMP エージェントです。CentOS 5 にインストールして試してみます。

まずは、ビルドに必要なパッケージをインストールします。

[root@co5v ~]# yum install -y gcc net-snmp-devel zlib-devel openssl-devel libxslt-devel pam-devel libtermcap-devel

ビルドします。Postgres Plus は、以前の記事で入れた通りです。pg_env.sh で pg_config にパスを通しておかないとビルドができませんので注意してください。

[root@co5v ~]# . /opt/PostgresPlus/9.0SS/pg_env.sh
[root@co5v ~]# tar zxvf pgsnmpd-1.0.tgz
(中略)
[root@co5v ~]# cd pgsnmpd-1.0/
[root@co5v pgsnmpd-1.0]# make
(中略)
[root@co5v pgsnmpd-1.0]# 

適当な設定を書いてみます。

[root@co5v pgsnmpd-1.0]# cat test.conf
com2sec readwrite default public
group MyRWGroup v2c readwrite
view all included .1 80
access MyRWGroup "" any noauth exact all all none
agentaddress localhost:10161
[root@co5v pgsnmpd-1.0]# 

実行してみます。

[root@co5v pgsnmpd-1.0]# ./pgsnmpd -c test.conf -C "dbname=postgres host=localhost user=postgres password=edb"
Could not set search path because of some problem with the set query
[init_smux] bind failed: Permission denied
PGSQL-SNMP-Ver1.0 is up and running.

net-snmp-utils を入れて、試しに叩いてみます。

[root@co5v ~]# yum install -y net-snmp-utils
(中略)
[root@co5v ~]# snmpwalk -v 2c -c public localhost:10161 mib-2.39
SNMPv2-SMI::mib-2.39.1.1.1.2.1 = OID: SNMPv2-SMI::enterprises.27645.1
SNMPv2-SMI::mib-2.39.1.1.1.2.11866 = OID: SNMPv2-SMI::enterprises.27645.11866
SNMPv2-SMI::mib-2.39.1.1.1.2.11874 = OID: SNMPv2-SMI::enterprises.27645.11874
(中略)
SNMPv2-SMI::mib-2.39.1.9.1.2.11874.1 = Hex-STRING: 07 DB 0A 1F 0F 1E 27 A8 2B 09 00
SNMPv2-SMI::mib-2.39.1.9.1.2.16393.1 = Hex-STRING: 07 DB 0A 1F 0F 1E 27 A8 2B 09 00
SNMPv2-SMI::mib-2.39.1.9.1.2.16393.1 = No more variables left in this MIB View (It is past the end of the MIB tree)
[root@co5v ~]# snmpwalk -v 2c -c public localhost:10161 mib-2.39.1.2.1.2.1
SNMPv2-SMI::mib-2.39.1.2.1.2.1 = STRING: "PostgreSQL 9.0.2 on x86_64-unknown-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46), 64-bit"
[root@co5v ~]# 

正直申し上げると、RDBMS-MIB による監視に馴染みがないので実用的かどうかは分からないのですが、パスワード認証なしでも状態が取れる点にメリットはあるかと思います。

2011年11月10日木曜日

ソースの入手と再ビルド ~ CentOS / Scientific Linux 編

お疲れ様です、サイオス 那賀です。

今どき組み込み系でもない限り、ほとんどの Linux ディストリビューションは高度なパッケージ管理機能(メタ・パッケージ管理機能)を備えており、ネットワーク上からパッケージを入手して、依存関係を解決しつつインストールやアップデートをできるようになっています。代表的なツールとしては、Red Hat 系の RPM パッケージ用の up2date, Yum や、Debian 系の deb パッケージに対する apt, Aptitude などであり、みなさんも日常的にご利用だと思います。

しかし残念なことに、せっかくのそれらの機能を、コンパイル済みのバイナリを入手するためにしか使っていない方が多いようです。せっかくのオープンソース OS 環境なのですから、ソースの入手・展開をしての解析、設定を変更しての再構築も容易になっていることを、もっと知ってもらいたいと思います。

まずはパッケージの入手です。yum-utils パッケージに含まれる yum-downloader コマンドを使うと、現在有効になっているレポジトリの "base" 等の名前に後ろに "-source" をつけたレポジトリを一時的に有効にし、ソース・パッケージを入手してきてくれます。

[root@co5v ~]# yum install -y yum-utils
(中略)
[root@co5v ~]#

下記の設定の追加は、CentOS 5 で必要です。Scientific Linux では最初から有効になっています。

[root@co5v ~] cat <<'EOF' > /etc/yum.repos.d/CentOS-Source.repo
[base-source]
name=CentOS-$releasever - Base Source Packages
baseurl=http://mirror.centos.org/centos/$releasever/os/SRPMS/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-$releasever

[updates-source]
name=CentOS-$releasever - Updates Source Packages
baseurl=http://mirror.centos.org/centos/$releasever/updates/SRPMS/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-$releasever
EOF
[root@co5v ~]#

以上で行け…るはずだったんですが、あれ? CentOS 5 で、書き置きの readme 一つを残して、ミラーレポジトリから SRPM が軒並み片付けられてしまっていますね。弱っちゃうな。では指示の通りに、かわりに以下を指定しましょう。バージョン (5.7) を直指定していますので、環境に合わせて変更してください。

[root@co5v ~] cat <<'EOF' > /etc/yum.repos.d/CentOS-Source.repo
[base-source]
name=CentOS-$releasever - Base Source Packages
baseurl=http://vault.centos.org/5.7/os/SRPMS/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-$releasever
[root@co5kdev ~]# 

試しに "which" パッケージのビルドをするために、ビルド時に依存するものを入れておきます。yum-builddep コマンドを使います。

[root@co5kdev ~]# yum-builddep -y which
(中略)
[root@co5kdev ~]# 

ようやく、ダウンロード & ビルドです。

[nonpriv@co5kdev ~]$ yumdownloader --source which
(中略)
[nonpriv@co5kdev ~]$ mkdir -p ~/rpm/{SOURCES,BUILD,SRPMS,RPMS}
[nonpriv@co5kdev ~]$ echo "%_topdir $HOME/rpm" > ~/.rpmmacros
[nonpriv@co5kdev ~]$ rpm -i which-2.16-7.src.rpm
[nonpriv@co5kdev ~]$ cd rpm/SPECS/
[nonpriv@co5kdev SPECS]$ rpmbuild -ba which.spec
(中略)
伸張ファイルの検査中: /usr/lib/rpm/check-files /var/tmp/which-2.16-7-root
書き込み完了: /home/nonpriv/rpm/SRPMS/which-2.16-7.src.rpm
書き込み完了: /home/nonpriv/rpm/RPMS/x86_64/which-2.16-7.x86_64.rpm
実行中(%clean): /bin/sh -e /var/tmp/rpm-tmp.38918
+ umask 022
+ cd /home/nonpriv/rpm/BUILD
+ cd which-2.16
+ rm -rf /var/tmp/which-2.16-7-root
+ exit 0
[nonpriv@co5kdev SPECS]

じゃんじゃんソースを入手して、SPEC をいじったりソースを読んだりしましょう。

2011年11月3日木曜日

PostgreSQL をバックエンドにして Zabbix を動かす

お疲れ様です、サイオス 那賀です。

Zabbix は、広く利用されている、オープンソースの統合監視ツールです。単純な監視ツールである NagiosMunin などと比べて、より詳細な監視が可能なエージェント型の構成をとり、プロキシやノードによる分散も考慮するなど、これ一つでとりあえず必要充分と言えるのではないでしょうか。

関連リンク:

さて、Zabbix はそのデータ保持に使用する RDBMS として PostgreSQL, MySQL, Oracle, SQLite をサポートしています。ところが世の Zabbix の書籍やインストール手順は、ほとんどが MySQL 用なので、せっかくですから PostgreSQL 用を書いてみようと思います。開発も含めて MySQL が Zabbix のプライマリ DB 扱いなので分は悪いのですが、それほど複雑なクエリは発行していないようですので、問題はないでしょう。

今回は CentOS 5 上に、日本のユーザ会配布の YUM レポジトリから Zabbix 1.8 を導入して構築をしてみます。各バイナリのバージョン等は、適宜現状のものに読み替えてください。また、同じ PostgreSQL でも、今回は米 EnterpriseDB 社Postgres Plus を使用してみます。

YUM によるインストールについてはこちらに案内があります。

[root@co5v ~]# rpm -Uvh http://www.zabbix.jp/binaries/relatedpkgs/rhel5/x86_64/zabbix-jp-release-5-3.noarch.rpm
(中略)
[root@co5v ~]# alternatives --display zabbix-jp-release
zabbix-jp-release -ステータスは自動です。
リンクは現在 /usr/share/zabbix-jp-release/zabbix-jp-1.6.repo を指しています。
/usr/share/zabbix-jp-release/zabbix-jp-1.1.repo - 優先項目 10
/usr/share/zabbix-jp-release/zabbix-jp-1.4.repo - 優先項目 20
/usr/share/zabbix-jp-release/zabbix-jp-1.6.repo - 優先項目 40
/usr/share/zabbix-jp-release/zabbix-jp-1.8.repo - 優先項目 30
現在の「最適」バージョンは /usr/share/zabbix-jp-release/zabbix-jp-1.6.repo です 。
[root@co5v ~]# alternatives --config zabbix-jp-release
 
4 プログラムがあり 'zabbix-jp-release' を提供します。

  選択       コマンド
-----------------------------------------------
   1           /usr/share/zabbix-jp-release/zabbix-jp-1.1.repo
   2           /usr/share/zabbix-jp-release/zabbix-jp-1.4.repo
*+ 3           /usr/share/zabbix-jp-release/zabbix-jp-1.6.repo
   4           /usr/share/zabbix-jp-release/zabbix-jp-1.8.repo

Enter を押して現在の選択 [+] を保持するか、選択番号を入力します:4
[root@co5v ~]# yum clean all
Loaded plugins: fastestmirror
Cleaning up Everything
Cleaning up list of fastest mirrors
[root@co5v ~]# yum install -y zabbix-agent zabbix-server-pgsql zabbix-web-pgsql
(中略)
[root@co5v ~]# chkconfig iptables off
[root@co5v ~]# service iptables stop
ファイアウォールルールを適用中:                            [  OK  ]
チェインポリシーを ACCEPT に設定中filter                   [  OK  ]
iptables モジュールを取り外し中                            [  OK  ]
[root@co5v ~]# chkconfig httpd on
[root@co5v ~]# service httpd start
httpd を起動中:                                            [  OK  ]
[root@co5v ~]# chkconfig zabbix-server on
[root@co5v ~]# service zabbix-server start
Starting zabbix server:                                    [  OK  ]
[root@co5v ~]# chkconfig zabbix-agent on
[root@co5v ~]# service zabbix-agent start
Starting zabbix agent:                                     [  OK  ]
[root@co5v ~]# 

次に Postgres Plus です。上記 URL から辿れる Postgres Plus のユーザーサイトへログインし、「ダウンロード」から "Postgres Plus Standard Server 9.0 for Linux 64 ビット" を入手します。

次に、CentOS 上に root でログインします。Postgres Plus にはウィザード形式の GUI インストーラもついているのですが、慣れてくると面倒なので、今回はコマンドラインから必要な情報を全て与えて、自動的にインストールをしてみます。オプションの詳細については、"--help" を参照してください。

[root@co5v ~]# chmod 755 postgresplus-9.0.2-1-linux-x64.bin
[root@co5v ~]# ./postgresplus-9.0.2-1-linux-x64.bin \
 --mode unattended \
 --superpassword edb \
 --enable-components dbserver \
 --disable-components \
  slony,pgJdbc,postgis,psqlOdbc,npgsql,pgbouncer,pgmemcache,pgagent \
 --dbInstallTune 0 \
 --updateNotification 0 \
 --existingEmail dummy@example.com \
 --existingpassword dummypass \
 --locale ja_JP.utf8
[root@co5v ~]# chkconfig --list postgresql-9.0
postgresql-9.0  0:off   1:off   2:on    3:on    4:on    5:on    6:off
[root@co5v ~]# service postgresql-9.0 status
pg_ctl: server is running (PID: 13099)
/opt/PostgresPlus/9.0SS/bin/postgres "-D" "/opt/PostgresPlus/9.0SS/data"
[root@co5v ~]#

もし ident しかないようでしたら、password なり md5 なりでパスワード認証をするようにしておきます。Postgres Plus では、デフォルトで local への all のアクセスを MD5 認証について許可するようになっているので不要ですが、一応以下のように明示的に設定し、サービスを再スタートさせて反映させておきます。標準的な RPM ベースの PostgreSQL ですと、ident 認証のみになっていると思います。

[root@co5v ~]# cp /opt/PostgresPlus/9.0SS/data/pg_hba.conf /opt/PostgresPlus/9.0SS/data/pg_hba.conf.orig
[root@co5v ~]# vi /opt/PostgresPlus/9.0SS/data/pg_hba.conf
[root@co5v ~]# diff -uNr /opt/PostgresPlus/9.0SS/data/pg_hba.conf.orig \
 /opt/PostgresPlus/9.0SS/data/pg_hba.conf
--- /opt/PostgresPlus/9.0SS/data/pg_hba.conf.orig
+++ /opt/PostgresPlus/9.0SS/data/pg_hba.conf
@@ -73,6 +73,7 @@
 # TYPE  DATABASE        USER            CIDR-ADDRESS            METHOD

 # "local" is for Unix domain socket connections only
+local   zabbix          zabbix                                  md5
 local   all             all                                     md5
 # IPv4 local connections:
 host    all             all             127.0.0.1/32            md5
[root@co5v ~]# service postgresql-9.0 restart
Restarting PostgreSQL 9.0:
waiting for server to shut down.... done
server stopped
waiting for server to start.... done
server started
PostgreSQL 9.0 restarted successfully
[root@co5v ~]#[root@co5v ~]#

次に、Zabbix 用のアカウントとデータベースを作成します。MySQL だとスキーマでネームスペースを作るところですが、そこは PostgreSQL ですので、データベース "zabbix" を作り、そこへデータを格納するようにします。ロールも "zabbix" とします。createuser の "-P" オプションで、新しいロールのためのパスワードを設定するようにします。うっかりクセで "-W" を指定しないように――"-W" は接続のためのパスワードであり、新ユーザのパスワードではありません。

[root@co5v ~]# echo localhost:5432:postgres:postgres:edb > ~/.pgpass
[root@co5v ~]# chmod 600 ~/.pgpass
[root@co5v ~]# . /opt/PostgresPlus/9.0SS/pg_env.sh
[root@co5v ~]# createdb -U postgres zabbix
[root@co5v ~]# createuser -U postgres --pwprompt --no-superuser --no-createrole --no-createdb zabbix
Enter password for new role: zabbix
Enter it again: zabbix
[root@co5v ~]# psql -U postgres -c "GRANT ALL PRIVILEGES ON DATABASE zabbix TO zabbix"
GRANT
[root@co5v ~]# echo localhost:5432:zabbix:zabbix:zabbix >> ~/.pgpass
[root@co5v ~]# psql -x -U zabbix zabbix -c "SELECT now()" # 試しに
-[ RECORD 1 ]----------------------
now | 2011-XX-XX 10:52:13.482851+09

[root@co5v ~]#

Zabbix の初期データを流しこんで、前準備は終了です。

[root@co5v ~]# psql -U zabbix zabbix < /usr/share/doc/zabbix-server-1.8.*/schema/postgresql.sql
(中略)
[root@co5v ~]# psql -U zabbix zabbix < /usr/share/doc/zabbix-server-1.8.*/data/data.sql
(中略)
[root@co5v ~]# psql -U zabbix zabbix < /usr/share/doc/zabbix-server-1.8.*/data/images_pgsql.sql
(中略)
[root@co5v ~]# 

後は、http://~/zabbix/ に接続して、設定を行います。今回は、第 4 ステップ "Configure DB connection" での設定は以下のようになりました。"Test connection" をクリックして、接続が "Ok" となれば次へ進みます。

Type:PostgreSQL
Host:localhost
Port:0 ("0" でデフォルトの 5432 を利用)
Name:zabbix
User:zabbix
Password:zabbix

それ以降の設定、使い方は、他の DB と同様です。web コンソールの初期パスワードは "Admin/zabbix" です。

同じ Zabbix でも、バックエンドを PostgreSQL にすることで、PostgreSQL ならではのオンライン物理バックアップや、ストリーミング・レプリケーションによる代替機の用意など、他 DB とは違った運用が考えられるのではないかと思います。

2011年11月1日火曜日

CentOS 6.0 での GUI ログイン画面の変更方法

サイオステクノロジー 金田です。
CentOS 6.0 から GUI ログイン画面にユーザー一覧が表示されるようになりました。(画像1)
画像1 CentOS 6.0 デフォルトのログイン画面

システムのユーザー数が少なければあまり気にならないのですが、多人数が登録されているシステムでは自分のユーザー名を探すのはちょっと面倒です。

そこで、ユーザー一覧を表示せず CentOS 5 系(画像2)のような、ユーザー名入力のログイン画面になるようにする設定を紹介します。
画像2 CentOS 5系のログイン画面

エディタで /etc/gconf/gconf.xml.defaults/%gconf-tree.xml を開いて、下記の行を検索します。

[編集前]
<entry name="disable_user_list" mtime="1312141029" type="schema" stype="bool" owner="gdm-simple-greeter" gettext_domain="gdm">
        <local_schema locale="C" short_desc="既知のユーザをログイン・ウィンドウに表示しない">
                <default type="bool" value="false"/>
                <longdesc>TRUE にすると、既知のユーザがログイン・ウィンドウへ表示されなくなります。</longdesc>
        </local_schema>
</entry>
<entry name="disable_user_list" のエントリ中の <default type="bool" value="false"/> の value の値を ture に変更します。

[編集後]
<entry name="disable_user_list" mtime="1312141029" type="schema" stype="bool" owner="gdm-simple-greeter" gettext_domain="gdm">
        <local_schema locale="C" short_desc="既知のユーザをログイン・ウィンドウに表示しない">
                <default type="bool" value="true"/>
                <longdesc>TRUE にすると、既知のユーザがログイン・ウィンドウへ表示されなくなります。</longdesc>
        </local_schema>
</entry>
ファイルを保存しログアウトすると、ユーザー名入力のログイン画面(画像3)が表示されます。
RHEL6 や Scientific Linux 6 でも同じ方法で変更できます。
画像3 変更後の CentOS 6.0 のログイン画面