Displaying posts tagged with

“お仕事”

WARNING: mismatch_cnt is not 0 on /dev/md0

Software RAID1を組んでいるサーバで、CentOS 5.3 -> 5.4にアップグレードしたところ、週末ごとに次のような警告メールが届くようになった。

/etc/cron.weekly/99-raid-check:

WARNING: mismatch_cnt is not 0 on /dev/md0

/proc/mdstat 等には特に異常などは見当たらないし、構成の異なる複数のサーバで同じ現象が起こったので、ハード的な問題ではないだろうと判断し、忙しかったこともあってそのままにしていた。しかしやはり気持ち悪いので、きちんと調べてみた。

メール中にある通り、この警告は /etc/cron.weekly/99-raid-check というスクリプトから送信されている。このスクリプトを提供しているのは mdadm パッケージで、5.4で更新されている。更新内容はレッドハットのサイトで RHBA-2009:1382-1 として提供されており、99-raid-check について説明しているのは、次の2箇所である。

* LinuxのソフトウェアRAIDスタックでは、データスクラビングがサポートされています(RAIDアレイのディスクを読み取って不良セクタを検索し、不良セクタが見つかると、他のディスクやパリティの情報を使用して、不良セクタを正常なデータで書き直します)。しかし、mdadmパッケージはこの機能を利用していませんでした。今回のパッケージは、cronジョブが/etc/cron.weeklyに追加されており、ディスクをチェックして不良セクタがないかどうかを確認し、見つかった場合は修復します。(BZ#233972)

* 今回のアップデートでは、mdadmに冗長アレイでの「データスクラビング」を可能にする新しい機能が追加されています。データスクラビングでは、冗長アレイ内のドライブ上で不良セクタが検索され、見つかった場合は他のドライブのデータを使用して修正されます。それによって、読み取りエラーを返すセクタは再構築されます。注:この新しいパッケージでは、データスクラビングはデフォルトでオンになっています。この機能は週1回実行され、実行中にある程度のパフォーマンス低下を引き起こす場合があります。パフォーマンス上の理由でこの機能を無効にしたい場合、アレイに対して実行されるチェックのタイプを管理したい場合、あるいは、どのアレイをチェックするかを制御したい場合は、/etc/sysconfig/raid-checkファイルを編集します。オプションを設定する方法の詳細は、そのファイルにコメントとして含まれています。(BZ#513200)

「データスクライピング(Data Scrubbing)」とは何か、なぜ重要なのかについては、ここで示されているBugzilla #233972およびその先のリンクに説明がある(一箇所リンクが切れているのはRAID/Software – GEntoo Linux Wikiだと思われる)。

データスクライピングを実行するには、root権限で次のコマンドを実行する。これによって不良セクタが検出され、自動的に修復される。99-raid-check が実行するのも、まさにこのコマンドである(少なくともデフォルトの設定においては)。

echo check > /sys/block/mdX/md/sync_action

ではこのコマンドと、問題の mismatch_cnt とはどう関係するのか。/etc/sysconfig/raid-check のコメントを読むと次のように書いてある。

If it finds good sectors that contain bad data (meaning that the data in a sector does not agree with what the data from another disk indicates the data should be, for example the parity block + the other data blocks would cause us to think that this data block is incorrect), then it does nothing but increments the counter in the file /sys/block/$dev/md/mismatch_count.

つまりセクタ自体は正常だが、中に入ってるデータがディスク間で異なる場合に mismatch_cnt が増加するということらしい。

ならば mismatch_cnt が 0 でないということは、ただちにRAIDが正常に機能していないことを意味するのだろうか?いろいろなMLの投稿などを読む限り、少なくとも swap パーティションを含むRAIDデバイスにおいては、全く正常であっても各ディスク間の内容が異なり得る…すなわち mismatch_cnt が0でないことがあり得るようだ。では swap を含まないパーティションの場合は?私の(また他のCentOS利用者の)ように、/boot のみを含む md0 の場合は?……これがよく分からない。この投稿を読む限り、ある種の状況においてはそうしたことも起こり得る、とのことである。

もしそうした状況に該当するなら。mismatch_cnt が 0 でなくとも、異なっているのは実際にはファイルシステムからアクセス不能な部分であって、システムの運用には影響しないのであれば。修復する方法はある。check の代わりに repair を使うことである。

#このコマンドを実行する前に以下の説明をよく読んでください!!
echo repair > /sys/block/mdX/md/sync_action

ただし /etc/sysconfig/raid-check には、次のような恐ろしいコメントが書いてある(強調は私による)。

The repair option does the same thing, but when it encounters a mismatch in the data, it automatically updates the data to be consistent. However, since we really don’t know whether it’s the parity or the data block that’s correct (or which data block in the case of raid1), it’s luck of the draw whether or not the user gets the right data instead of the bad data.

というわけで、以下は「それでも自己責任でこの方法に賭けるぜ!」という方のみ読んでください。

まず各デバイスの mismatch_cnt の値をチェックしておく。

cat /sys/block/md0/md/mismatch_cnt

そして repair を実行する。

sudo sh -c 'echo repair > /sys/block/md0/md/sync_action'

進行状況は /proc/mdstat で確認できる。

cat /proc/mdstat

repair を実行しただけでは mismatch_cnt は更新されないので、もう一度 check を実行する。進行状況はやはり /proc/mdstat で確認できる。

sudo sh -c 'echo check > /sys/block/md0/md/sync_action'

終了したら mismatch_cnt をチェックして、0 になっているか確認する。

cat /sys/block/md0/md/mismatch_cnt

……

参考にしたサイトははてブの mismatch_cnt タグにまとめてあるので、この記事に書いてあることを鵜呑みにせず、自分で調べ自分で判断するようお願いします。

WYSIWYGエディタがIE8で動かない

designMode/contentEditable を使用したWYSIWYGエディタが、IEのバージョンを8に上げたら正常に動かなくなった、という相談を受けた。ほとんどの機能は正常なのだが、画像の挿入だけがうまくいかないという。

いろいろ調べた結果、execCommand メソッドで InsertImage を実行する前に、対象となる window の focus メソッドを呼び出せば正常に動作することが分かった。

var iframe = document.getElementById('editor');
    iframe.contentWindow.document.designMode = 'on';
 
function insertImage(path) {
    iframe.contentWindow.focus(); //ココ
    iframe.contentWindow.document.execCommand('insertimage', false, path);
}

問題の解決にあたっては、下記のフォーラムなどで「テキスト選択中なら正常に動く」という証言があったことがヒントになった。

execCommand – specifically InsertImage stops working with IE8 upgrade

RedmineでGitのリモートリポジトリを参照

Redmineでブラウズの対象とするには local かつ bare なリポジトリでなければならないので、そのままでは使えない。そこでまず対象リポジトリのミラーとなるbareリポジトリを作る。

git clone --bare git://host/path.git
cd path
git remote add --mirror origin git://host/path.git

最近のバージョンの git では clone のオプションに –mirror を直接指定することができるらしいが、1.5.6 では上の手順が必要だった。

# git-1.6.0.6以降
git clone --mirror git://host/path.git

リポジトリを同期するには、ミラーリポジトリ内で fetch を実行する。cronで定期的に実行するよう設定しておけば実用上は十分だろう。

git fetch origin

あとはこのミラーリポジトリのパスをRedmineに設定しておく。

異なるブランチを使用する

Redmineの設定画面にはブランチ名の項目は無い。
lib/redmine/scm/adapters/git_adapter.rb
をチェックしたところ、常に”現在の”ブランチが使用されるようだ。

@branch ||= shellout("#{GIT_BIN} --git-dir #{target('')} branch") { |io| io.grep(/\*/)[0].strip.match(/\* (.*)/)[1] }

改造するのも面倒なので、異なるブランチには異なるリポジトリを割り当てることにした。上と全く同じ手順で bare リポジトリを作った後、HEADファイル内の参照を書き換える(bareリポジトリ なので checkout は使用できない)。

ref: refs/heads/your_branch

fetch の手順などは全く同じで良い。

mymemcheckをCentOSで動かす

サーバ/インフラを支える技術』に載っていた mymemcheck を試してみようと思って CentOS 5 上で実行してみたところ、いくつかの Perl モジュールが足りなくて動かなかった。例によって rpmforge で検索してみたら、やはり見つかった。

sudo yum --enablerepo=rpmforge install perl-Readonly perl-UNIVERSAL-require

相変わらず便利過ぎるぜ rpmforge。

BlockHosts の導入

ブルートフォースアタックからの防衛ツール BlockHosts 導入手順。環境は CentOS 4。

インストール

rpmで導入する場合

wget http://www.aczoom.com/tools/blockhosts/BlockHosts-2.4.0-1.noarch.rpm
sudo rpm -Uvh BlockHosts-2.4.0-1.noarch.rpm

もしくはソースからインストールする場合

wget http://www.aczoom.com/tools/blockhosts/BlockHosts-2.4.0.tar.gz
tar xvzf BlockHosts-2.4.0.tar.gz
cd BlockHosts-2.4.0
sudo python setup.py install

どちらの方法を使っても、設定ファイルは /etc/blockhosts.cfg にインストールされるし、ログローテーションのための設定ファイル /etc/logrotate.d/blockhosts もインストールされる。

/etc/blockhosts.cfg の設定

まずは最低限の設定を行う。CentOS ならほとんどの場合はデフォルトで良いと思うが、

HOSTS_BLOCKFILE = "/etc/hosts.allow"
WHITELIST = [ "127.0.0.1", "192\.168\.2\..*", ]
LOGFILES = [ "/var/log/secure", ]

このあたりは明示的に設定しておいた方が良いと思う。WHITELIST に追加する設定は自分の環境にあわせて。

/etc/hosts.allow に設定追加

こちらもまずは最低限の情報を書いて、動作確認をする。

#---- BlockHosts Additions
#---- BlockHosts Additions

この状態で以下のコマンドを実行し、正しく解析結果が表示されることを確認。

sudo blockhosts.py --verbose --dry-run

次に –dry-run オプションを外し、/etc/hosts.allow の書き換えが正しく行われることを確認する(BlockHosts Additions の間に情報が書き込まれる)。

sudo blockhosts.py --verbose

最後に /etc/hosts.allow の末尾に blockhosts.py の起動設定を追加する。以下は一例

sshd: ALL: spawn /usr/bin/blockhosts.py --verbose --echo "%c-%s" >> /var/log/blockhosts.log 2>&1 : allow

その後の設定

ほとんどの設定は /etc/blockhosts.cfg の中でも、blockhosts.py のコマンドラインオプションとしても(つまり /etc/hosts.allow の中でも)設定できる。詳しくは blockhosts.cfg の中のコメントや blockhosts.py –help を参照。

試していないが、「ipblock」の設定を行うことで、TCP/IP レベルでのブロックも行えるようだ。ip コマンドで無効なルートを設定するか、iptables でフィルタリングするか選べるらしい。blockhosts.cfg より:

#IPBLOCK = "" # (default)
#IPBLOCK = "ip route" # or use full path "/sbin/ip route"
#IPBLOCK = "iptables" # or use full path "/sbin/iptables"
# "ip route": Do TCP/IP blocking using route commands to setup null-routes.
#    ip route add  via 127.0.0.1
# "iptables": Do TCP/IP blocking, using iptables packet filtering.
#    iptables --append blockhosts --source  -j DROP

cciss経由で取得したHDDの温度をmuninでグラフ化

CCISS (HP/Compaq Smart Array Controller) に接続された HDD の SMART 情報を読み出し、温度を munin の hddtemp_smartctl プラグインでグラフ化する。

cciss に対応する smartmontools は 5.38 以降(stable)。CentOS 5.3 では標準でこのバージョンがインストールされるが、あいにく対象サーバはCentOS 4だったので、ソースからインストールした。

tar xvzf smartmontools-5.38.tar.gz
cd smartmontools-5.38
./configure
make
sudo make install

/usr/local/sbin に新たにインストールされた smartctl を使用して、温度その他の情報が取得できることを確認。以下表示例。

$ sudo /usr/local/sbin/smartctl -A -d cciss,0 /dev/cciss/c0d0
smartctl version 5.38 [i686-pc-linux-gnu] Copyright (C) 2002-8 Bruce Allen
Home page is http://smartmontools.sourceforge.net/

Current Drive Temperature:     26 C
Drive Trip Temperature:        65 C
Manufactured in week 50 of year 2006
Recommended maximum start stop count:  10000 times
Current start stop count:      19 times
Elements in grown defect list: 0

続いてmunin のプラグイン設定ファイル(/etc/munin/plugin-conf.d/hddtemp_smartctl )に設定を追加する。デバイス名の後に _[番号] を付けるのがポイント。

[hddtemp_smartctl]
user root
env.smartctl    /usr/local/sbin/smartctl
env.drives      cciss/c0d0_0 cciss/c0d0_1
env.type_cciss/c0d0_0  cciss,0
env.type_cciss/c0d0_1  cciss,1

これで値が取得できるようになる…のだが、うまくグラフが表示されない。デバイス名に / が含まれているのがまずいらしいので、プラグインファイル /usr/share/munin/plugins/hddtemp_smartctl を少し改造。munin-node-1.2.5用のパッチを置いておく。

こんな感じで表示されるようになる。

hddtemp_smartctlによるグラフ表示

hddtemp_smartctlによるグラフ

visitors でリモートホストの集計

高速・軽量なアクセス解析ツール visitors およびその日本語化バージョン。素晴らしいツールなのだが、デフォルトではアクセス元ドメインの集計が全て「numeric IP」になってしまうのが難点だった。

そこで日本語化バージョンを元に、まずはIPアドレスごとに集計を行うよう修正した(パッチダウンロード)。

diff -ur visitors_0.7.orig/visitors.c visitors_0.7/visitors.c
--- visitors_0.7.orig/visitors.c	2007-08-20 19:11:54.000000000 +0900
+++ visitors_0.7/visitors.c	2009-03-28 17:38:59.000000000 +0900
@@ -1607,13 +1607,9 @@
 	char *tld;
 	int res;
 
-	if (vi_is_numeric_address(hostname)) {
-		tld = "numeric IP";
-	} else {
-		tld = strrchr(hostname, '.');
-		if (!tld) return 0;
-		tld++;
-	}
+	tld = hostname;
+	if (!tld) return 0;
+
 	res = vi_counter_incr(&vih->tld, tld);
 	if (res == 0) return 1;
 	return 0;

あとは出力時に逆引きを行えば良い。本当は visitors.c 内で行うように修正すべきなんだろうが、よく分からないのでPerlのワンライナーで変換することにした(下例ではIPアドレスっぽいテキストを全て変換してしまうので、もう少し真面目に書いた方が良いとは思うが……)。

visitors -A -m 45 -o html access_log | perl -pe \
's%(\d{1,3}\.){3}\d{1,3}%gethostbyaddr(pack("C4", split(/\./, $&)), 2) || $&%e' \
> out.html

元々 visitors のこの機能は、トップレベルドメインを集計して国別のアクセス傾向を知るためのものなので、リモートホストの集計に用いるのは邪道かも知れない。しかし実用上はこの方が役に立つ機会は多いと思う。

この改造にあたっては以下のページを参考にした:

こちらではまずアクセスログに記録されたIPアドレスを全て逆引きする方法を紹介されているが、ログが何十万行もある場合は逆引きに時間がかかり過ぎる……。この用途に限って言えば、IPアドレスで集計して上位のアドレスだけ逆引きするという方針で十分だろう。

OpenX のインストール(日本語対応)

オープンソースの広告配信サーバ OpenX。バージョン2.6からは日本語リソースファイルもデフォルトで含まれているが、若干問題が残っている。

以下、OpenX 2.6.4 を $OPENX_PATH に www.example.com というドメインでインストールした場合の説明。MySQLは 5.0 系を使用。

データベースの文字コード設定

インストール完了後、管理画面からデータを追加する前に設定ファイルを修正する。修正すべきファイルは
$OPENX_PATH/var/www.example.com.conf.php
このファイルの中の clientCharset を utf8 に変更する。デフォルトでは多分 latin1 になっているはず。

[databaseCharset]
checkComplete=1
clientCharset=utf8

この設定をしておかないと「一見正常に動いているがDB内部では文字列が壊れている」という状態になる。

Excelの文字化け修正

デフォルトではレポート画面で出力できるExcelファイルが文字化けする。これは OpenX が内部で使用しているPEARパッケージ Spreadsheet_Excel_Writer の問題。バグレポートからパッチを落としてきて適用する。

cd $OPENX_PATH
patch -p0 < excel-all-in-one-patch.diff

ちなみにこのパッチは私が投稿したものだが、フォーラムで紹介されていた複数のパッチを一つにまとめただけで、修正の内容は理解していない。また mbstring が必須となっているため、このまま本体に取り込まれる可能性はまずないと思われる。

CentOSで最新のPHP 5.2を使用する

サードパーティのリポジトリを利用することで、2009年3月20日現在最新のphp-5.2.9をyumでインストールすることができる。リポジトリ管理者の素晴らしい仕事には頭が下がるばかりだ…。

注意:この方法でインストールされる php-mysql は MySQL 5.1.30 の libmysqlclient とリンクされる。

English : Repository Configuration – Les RPM de Remiに従ってEPELとLes RPM de Remiのリポジトリを追加。CentOS 5の場合は

wget http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-2.noarch.rpm
wget http://rpms.famillecollet.com/el5.i386/remi-release-5-6.el5.remi.noarch.rpm
rpm -Uvh remi-release-5*.rpm epel-release-5*.rpm

php-mysql をインストールする場合は、予め remi-test リポジトリから mysqlclient16 パッケージをインストールしておく。

sudo yum --enablerepo=remi-test install mysqlclient16

自分が必要とするパッケージをインストールする(パッケージによってはEPEL内のパッケージに依存することがある)。

sudo yum --enablerepo=epel,remi install php php-cli php-mysql php-gd

インストール後はリポジトリ管理者のブログLes RPM de Remiを常にチェックしておくことをおすすめする。PHPの新しいバージョンが出た場合、今までは数日中には対応されてきた。しかしアップデートに伴って、時々パッケージの構成が変わったりライブラリのバージョンが変わったりして、すんなりアップデートできなくなることもあった。そのあたりは自己責任で。

Zend Framework 徹底入門

PHP用のMVCフレームワークを選定している。

『Zend Framework徹底入門』は、この手のフレームワーク本としてはちょっと珍しいくらいに内容が充実していて、2chのZFスレでも非常に評価が高い(あまりにも絶賛意見が多いので当初は「宣伝乙」とか思ってました…ごめんなさい)。もともとZFは公式ドキュメントが充実しているので、この本と合わせればそれでもう十分な情報量になる。

しかしいくら情報量が多くても、フレームワーク自体が使いにくければどうしようもない。そして私にとってZFは、使いやすいとは言い難い。一人のプログラマとして設計やコードを眺めるととても美しいと感じるのだが、いざ一人のユーザとして使ってみると、あらゆる種類の不親切さにうんざりしてしまう。

”Rails以前”のフレームワークを現代風に洗練した感じ、とでも言おうか。Railsは「皆さんはもっとラクをして良いんですよ」というメッセージを堂々と打ち出してきたことが衝撃的だった。ZFにはそういう意識は感じられない。優れた設計・コードはあっても、使いやすくするための工夫は少ない。

ZFの上にもう一枚、自分用フレームワークの層を構築するべきか。それとも他のフレームワークをあたるのが早いか。