CentOS に memcached をインストールする

以前は yum でサクッとインストールできたと記憶しているのだけど、今は yum でインストールできないようなので、ソースからインストールしました。手間がかかったので、次回へのメモとして、ログを残しておきます。

まず、memcached が使うイベント通知APIの libevent のバージョンを確認。

# rpm -q libevent
libevent-1.1a-3.2.1

1.1系と古いので、新しいものを入れます。ソースは公式サイトから、安定版のうち最新のものを持ってきます

# cd /usr/local/src
# wget http://www.monkey.org/~provos/libevent-1.4.13-stable.tar.gz
# tar xvfz libevent-1.4.13-stable.tar.gz
# cd libevent-1.4.13-stable
# ./configure --prefix=/usr/local/libevent
# make
# make install

続いて、 memcached をインストールします。ソースは公式サイトから。

# cd /usr/local/src
# wget http://memcached.googlecode.com/files/memcached-1.4.5.tar.gz
# tar xvfz memcached-1.4.5.tar.gz
# cd memcached-1.4.5
# ./configure --with-libevent=/usr/local/libevent/
# make
# make install

起動コマンドを作ってサービス登録します。といっても、そのままコピーですが。キャッシュ容量やポート番号を変えるなどしたい場合は、このスクリプトのなかをいじりましょう。

# cp /usr/local/src/memcached-1.4.5/script/memcached.sysv /etc/rc.d/init.d/memcached
# chkconfig --add memcached
# chkconfig --list memcached

用意が整ったところで、起動します。

# /etc/rc.d/init.d/memcached start

ここで、起動せずに次のようなエラーが出ることがあります。

memcached: error while loading shared libraries: libevent-1.4.so.2: cannot open shared object file: No such file or directory

今回は libevent を /usr/local/libevent にあるものを使うため、ldconfig してあげなければいけませんでした。

# echo "/usr/local/libevent/lib" > /etc/ld.so.conf.d/libevent.conf
# ldconfig

このあと起動すれば、問題なく立ち上がると思います。動作確認をします。

$ telnet localhost 11211
stats
STAT pid 11440
STAT uptime 71
STAT time 1272779578
STAT version 1.4.5
STAT pointer_size 32
STAT rusage_user 0.000000
STAT rusage_system 0.010000
STAT curr_connections 10
STAT total_connections 11
STAT connection_structures 11
STAT cmd_get 0
STAT cmd_set 0
STAT cmd_flush 0
STAT get_hits 0
STAT get_misses 0
STAT delete_misses 0
STAT delete_hits 0
STAT incr_misses 0
STAT incr_hits 0
STAT decr_misses 0
STAT decr_hits 0
STAT cas_misses 0
STAT cas_hits 0
STAT cas_badval 0
STAT auth_cmds 0
STAT auth_errors 0
STAT bytes_read 7
STAT bytes_written 0
STAT limit_maxbytes 67108864
STAT accepting_conns 1
STAT listen_disabled_num 0
STAT threads 4
STAT conn_yields 0
STAT bytes 0
STAT curr_items 0
STAT total_items 0
STAT evictions 0
STAT reclaimed 0
END

stats と打つとステータスが、バーっと流れるので確認しましょう。プロンプトを抜けるときには、いつもどおりで quit と打てば OK。

最近セットアップを自動化しているせいで、こうしてソースから入れるのは2年ぶりくらい。ldconfig とか忘れてしまっていて、やり方を思い出すのに、ムダに時間かかってしまいました。うーむ。

以上、おつかれさまでした。

特定のサイズのファイルを生成する

ファイル操作のテストなどで、特定の大きさのファイルを作成したいときがあります。そんなときは、 dd コマンドを使うと簡単に作ることができます。

dd if=/dev/zero of=test_file bs=1M count=10

上記の例だと、カレントディレクトリに「test_file」という10MBのファイルが生成されます。便利。

vim で開発するときに知らないと損する小技

転職を機に perl を書くようになって以来、vim 一本で開発のすべてを行っています。

かつては、何と java を vi で書いていたこともあったし、運用でしばしば vi を使う機会があったので、基本的な操作は身に付いていたんですが、本格的に vi を使うようになって色々と便利な技があることを知ったのでシェアメモ。

まずは、文字コード変換。

:e ++enc=shift_jis
:e ++enc=iso-2022-jp
:e ++enc=euc_jp

これができないと、そもそも vim 一本で開発することができないという話。テンプレ編集やメール系の開発するときに便利すぐる。

続いて画面分割

:sp

これで画面が上下に分割して編集できます。画面を切り替える場合は、Ctrl+w を2回。プログラムを書いていて、「あ、これって他はどうしてるんだっけ?」と思って一時的に参照したい場合に便利です。

現在カーソルのある画面を閉じる場合は、

:close

現在カーソルのある画面以外をすべて閉じて、通常モードに戻す場合は、

:only

diff のように行単位で違いを眺めながら編集したい場合は、

Ctrl+w → v

これで垂直分割になります。純粋に 2ファイルの diff を見るのならば、vimdiff で OK なんですが。

分割したそれぞれの画面で別のファイルを表示するには、その画面に切り替えて、

:e ファイル名

これで、新しいファイルの編集モードに入れます。

ファイルを開くという意味では、編集中のファイルにあるパスにカーソルを合わせて

gf

これで、そのパスにあるファイルを開くことができます。これ、ヤバイです。芋づる式にプログラムを編集できます。grep 結果をファイルにリダイレクトしておいて、あとで開いて順番に見ていきながら編集する場合に重宝しました。


画面分割は、「screen 使えば良いんじゃないの?」という話もありますが、ちょっとした比較には vim の画面分割はダントツに力を発揮します。特に、ノートPCやサーバのコンソールのように、小さい画面で頑張らないといけない時なんかは、知っていると知らないとでは作業効率に雲泥の差が出ますよ、ホントに。

ということで便利技をいくつか書いてきましたが、要するに「java × eclipse の開発は便利で良かったなぁ」ということです。 vim でどんなに頑張っても、さすがにアレにはかなわないですね。

bashでヒアドキュメントをリダイレクト

ヒアドキュメントを使って、ファイルに内容を書き出そうと思ったんだけど、どこにリダイレクトを書くのか分からなくて苦戦した。ううう。

正解はこちら。最初に指定しておくのか。なるほど。

cat << HERE >> /tmp/hoge 2>&1
xxxxxx
yyyyyy
zzzzzz
HERE

bashのヒアドキュメントは、メール送信以外で使ったのは、これが初めてかもしれない。便利な仕組みだけど、あんまり用途が思いつかない。

NULL文字を削除する

csvデータをpostgresqlにインポートしようとしたら、エラーが。

ERROR:  invalid byte sequence for encoding "SJIS": 0x00

NULL文字が含まれているのが、納得いかないようす。NULL文字は目で見えない制御文字なので、どうやって削除したもんかなーと思ったら、trコマンドで簡単に除去できました。

$ cat src.csv | tr -d "\000" > dest.csv

これでインポートはバッチリでした。

続きを読む "NULL文字を削除する"

Linuxの圧縮/解凍コマンドまとめ

マイナーな圧縮形式になるとコマンドを忘れがちなので、まとめのメモ。

まずは基本の gz 形式から。(さすがに忘れないけど)

圧縮
$ gzip filename
解凍
$ gunzip filename.gz

続いて、tar.gz (tgz) 形式。(これも忘れないなあ)

圧縮
$ tar cvfz dirname.tar.gz dirname
解凍
$ tar xvfz dirname.tar.gz

bzip2 (bz2) 形式。

圧縮
$ bzip2 filename
解凍
$ bzip2 -d filename.bz2

tar.bz2 形式。

圧縮
$ tar cvfj dirname.tar.bz2 dirname
解凍
$ tar xvfj dirname.tar.bz2

Windowsとのデータやり取りの基本、ZIP形式。

圧縮
$ zip filename.zip file1 file2
解凍
$ unzip filename.zip

これまたWindowsとデータ交換するとよく出てくるLZH形式。

圧縮
$ lha -a filename.lzh file1 file2
解凍
$ lha -e filename.lzh

こんなところでしょうか。個人的には、tar.bz2形式とLZH形式の解凍が、いつも一発でいきません。あうあう。どうもオプションが覚えられないんだよなあ。チートシート、チートシート、と。

FTP専用ユーザーを作ってみる

年に1回くらい需要があることが分かったので、ここらへんでメモしてみる。

# useradd -s /sbin/nologin -M ftpuser
# passwd ftpuser
# mkdir -p /ftp/userdir
# usermod -d /ftp/userdir ftpuser
# chown ftpuser:ftpuser /ftp/userdir
# chmod 705 /ftp/userdir

useradd で /sbin/nologin を指定することで、telnet などでログインできないユーザを作成できる。また、-M オプションを付けると、ホームディレクトリを作成せずにユーザを作成するので、不要なメールボックスが作成されないで済む。FTP先のディレクトリは、usermod で後から設定してあげればOK。

ざっくりこんな感じ。

ただ、qmail が動いていると、メールボックスは無いんだけれども、/etc/passwd にエントリされるだけで、有効なアカウントと判断してしまう。だもんで、例えば ftpuser 宛にメールをすると、ローカル配送してしまう。まあ、メールボックスが無くてエラーになるので、目的を達成してはいるんだけど、"no mailbox" なエラーじゃないので、いただけない。

ここらへん、厳密に対処するのであれば、qmail でメールアカウントだけを削除する方法のように、ごにょごにょしてやらないといけない。ちょっと大げさ。

色んなサービスが動いていると、細かいところで厄介になるなー。

SSLのパスフレーズ入力を回避する方法

SSLを設定してApacheを立ち上げようとすると、秘密鍵のパスフレーズを問合せてくる。

手動で運用している分には問題ないのだけれども、スクリプトで起動するような操作をする場合に面倒くさいことになる。そこで、パスフレーズの入力を回避してみる。

# openssl rsa -in server.key -out server.key.nopass

これで、元の秘密鍵からパスフレーズ抜きの鍵を生成して、これを SSLCertificateKeyFile に指定してあげれば、次回の起動からはパスフレーズの入力なしで、Apacheを起動できます。わーい、便利。

ただし当然ながら、これはセキュリティ上、好ましくないので、単純に「めんどくせえなあ」ということなら、やめておいた方が良いと思います。そういう意味では、裏技ですね。

ちなみに、

# apachectl startssl

として起動しようとしたら、怒られてしまった。

Apache2.2からは、startssl などと書かずに、普通に start や graceful でSSL起動ができるようになったとのこと。ほう、こりゃまた便利な世の中ですなあ。

ということで、

# apachectl start

のコマンド一発で、パスフレーズ入力もなく、SSLを意識せずにApacheの運用が出来るようになりました。お疲れさまでした。

独自ネームサーバでドメイン解決できなくて

新規にドメインを取得し、自分でネームサーバを立てて運用をしようとするも、うまくいかずに数日ほどハマる。

ゾーンファイルを書き換えたりすることは日常的に行っており、DNSの仕組みも把握していたので、ゼロから構築するのもイージーだろうと思っていたら、まあ、色んなミスを重ねてハマりまくった。反省の意味も込めて、メモ書き。

続きを読む "独自ネームサーバでドメイン解決できなくて"

IPエイリアスでサーバに複数のIPを割り当てる

1台のサーバで複数ドメインの SSL 対応をやることになって、サーバ(というかNIC)に複数のIPアドレスを割り当てることになった。名前ベースの VirtualHost だと SSL 対応できないからね。VirtualHost で複数 SSL 運用するのであれば、IPベースしかないわけです。

こういう場合は、IPエイリアスを使うのが定石。

# ifconfig eth1:0 xxx.xxx.xxx.11 netmask 255.255.255.240
# ifconfig eth1:1 xxx.xxx.xxx.12 netmask 255.255.255.240

こんな感じで、NIC(ここではeth1)に複数IPアドレスを割り当てていけば OK なんだけど、このままだと、再起動時に設定が無効になっちゃう。仕方なく network の起動スクリプトに、同じコマンドを記述して起動していたんだけど、Redhat なら静的ファイルで管理できるみたい。

# cat /etc/sysconfig/network-scripts/ifcfg-eth1
DEVICE=eth1
BOOTPROTO=static
BROADCAST=xxx.xxx.xxx.15
HWADDR=xx:xx:xx:xx:xx:xx
IPADDR=xxx.xxx.xxx.10
NETMASK=255.255.255.240
NETWORK=xxx.xxx.xxx.1
ONBOOT=yes
TYPE=Ethernet

という NIC に対して、次のようにエイリアスファイルを作っていけば OK みたい。

# vi /etc/sysconfig/network-scripts/ifcfg-eth1:0
DEVICE=eth1:0
BOOTPROTO=static
BROADCAST=xxx.xxx.xxx.15
HWADDR=xx:xx:xx:xx:xx:xx
IPADDR=xxx.xxx.xxx.11
NETMASK=255.255.255.240
NETWORK=xxx.xxx.xxx.1
ONBOOT=yes
TYPE=Ethernet

# vi /etc/sysconfig/network-scripts/ifcfg-eth1:1 DEVICE=eth1:1 BOOTPROTO=static BROADCAST=xxx.xxx.xxx.15 HWADDR=xx:xx:xx:xx:xx:xx IPADDR=xxx.xxx.xxx.12 NETMASK=255.255.255.240 NETWORK=xxx.xxx.xxx.1 ONBOOT=yes TYPE=Ethernet

これまで1枚の NIC に対して 1つのファイルなんだと思っていたので、エイリアスの場合どうするのかなーなんて思っていたんですが、IPエイリアスごとにファイルを用意して管理できるんですねー。これは良いこと知りました。ありがとうございます。

Apache2.2とTomcatを連携させるmod_proxy_ajp

Apache2.2系では、Tomcatと連携するのに、mod_jk を入れずとも mod_proxy_ajp モジュールを使って対応できるようなので、試してみた。

mod_proxy.so と mod_proxy_ajp.so が必要になるので、次のようにコンパイルする。とりあえず、他にも色々と必要だったりしたので、次のようにした。

# tar xvfz httpd-2.2.8.tar.gz
# cd httpd-2.2.8/
# ./configure --prefix=/usr/local/apache \
	--enable-so \
	--enable-shared \
	--enable-rewrite \
	--enable-ssl=shared \
	--with-mpm=worker \
	--enable-deflate \
	--enable-headers \
	--enable-dav=no \
	--enable-proxy-ajp \
	--enable-proxy \
	--enable-mods-shared=all
# make
# make install

Tomcat 側のデフォルトのAJPポートは 8009 なので、変更なければ、httpd.conf に次のように書けば終わり。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ajp_module modules/mod_proxy_ajp.so

<Location /manager/> ProxyPass ajp://xxx.xxx.xxx.xxx:8009/manager/ </Location>

これで、それまで http://xxx.xxx.xxx.xxx:8080/manager とアクセスしていたところ、http://xxx.xxx.xxx.xxx/manager とアクセスできるようになる、と。mod_jk に比べてすんごくラクチン。これは良いかも。

nss_ldap の接続タイムアウトを変える

PAM (Pluggable Authentication Modules)認証で、pam_ldap.so モジュールを使用するとき、LDAPに接続できないと、長いこと待たされる。LDAP側で管理しているユーザではなく、shadowファイルなどで認証チェックがOKとなっても、2分くらい待たされる。なんでじゃ。

PAMのsystem-authはこんな感じ。

#%PAM-1.0
auth        required      /lib/security/pam_env.so
auth        sufficient    /lib/security/pam_unix.so likeauth nullok
auth        sufficient    /lib/security/pam_ldap.so use_first_pass
auth        required      /lib/security/pam_deny.so

account required /lib/security/pam_unix.so broken_shadow account [default=bad success=ok user_unknown=ignore service_err=ignore system_err=ignore authinfo_unavail=ignore] /lib/security/pam_ldap.so account required /lib/security/pam_permit.so
password required /lib/security/pam_cracklib.so retry=3 type= password sufficient /lib/security/pam_unix.so nullok use_authtok md5 shadow password sufficient /lib/security/pam_ldap.so use_authtok password required /lib/security/pam_deny.so
session required /lib/security/pam_limits.so session required /lib/security/pam_unix.so session optional /lib/security/pam_ldap.so

ついでに、nsswitch.confも。

 passwd:     files ldap
 shadow:     files ldap
 group:      files ldap

まあ、よくある基本的なLDAP認証の設定です。これで、LDAPに登録したアカウントでの認証もできるし、無論LDAPに登録していない元からのアカウントでの認証もできる。つまり、LDAPが落ちていても、shadowファイルとかに情報があれば、認証をパスできるわけです。

ところが、実際にLDAPを落として、SSHでログインを試みると、ログイン認証ごときに尋常じゃなく待たされる。ログ(/var/log/secure)を見てみたら、こんなことに!

sshd[29791]: Accepted password for plab from xxx port 3496 ssh2
sshd[29793]: nss_ldap: failed to bind to LDAP server ldap://xxx: Can't contact LDAP server
sshd[29793]: nss_ldap: failed to bind to LDAP server ldap://xxx: Can't contact LDAP server
sshd[29793]: nss_ldap: reconnecting to LDAP server (sleeping 4 seconds)...
sshd[29793]: nss_ldap: failed to bind to LDAP server ldap://xxx: Can't contact LDAP server
sshd[29793]: nss_ldap: reconnecting to LDAP server (sleeping 8 seconds)...
sshd[29793]: nss_ldap: failed to bind to LDAP server ldap://xxx: Can't contact LDAP server
sshd[29793]: nss_ldap: reconnecting to LDAP server (sleeping 16 seconds)...
sshd[29793]: nss_ldap: failed to bind to LDAP server ldap://xxx: Can't contact LDAP server
sshd[29793]: nss_ldap: reconnecting to LDAP server (sleeping 32 seconds)...
sshd[29793]: nss_ldap: failed to bind to LDAP server ldap://xxx: Can't contact LDAP server
sshd[29793]: nss_ldap: reconnecting to LDAP server (sleeping 64 seconds)...
sshd[29793]: nss_ldap: failed to bind to LDAP server ldap://xxx: Can't contact LDAP server
sshd[29793]: nss_ldap: could not search LDAP server - Server is unavailable

どうやら認証処理うんぬんではなく、LDAPサーバに接続できるまで、時間を置きながら最大5回までチャレンジしているため、時間がかかりまくっているみたい。何らかの原因でLDAPサービスが落ちたとき、復旧でSSH接続しようとしたら2分かかりました、ってのはキツイ。もうちょっと空気読もうよ、nss_ldapさんっ!

実際、LDAPサービスの死活を判断するのに、トータル124秒も待って5回も再接続を試みる必要があるケースは少ないと思う。同じネットワークエリア内にドメインコントローラを置いたりするなら、これは大げさすぎるんじゃないか、と。

ということで、nss_ldapの再試行回数やタイムアウト時間を変更する方法。

続きを読む "nss_ldap の接続タイムアウトを変える"

Apacheをroot権限で動かす裏ワザ

Apacheはroot権限で起動したあと、セキュリティ確保のため、子プロセスを一般ユーザー(nobodyとか)で生成する。今日は、この子プロセスも、rootで起動しちゃおうという話。

CGIは通常、子プロセスの一般ユーザー権限で実行される。そのため、より高い権限が必要なファイル操作を行おうとすると、パーミッションエラーになったりする。この手の問題には、suexecで対処するのがセオリーだけど、「そもそも実行ユーザーをrootにしちゃえば、何でもできるんじゃないの?」というコペルニクス的転回があって、試してみたら、できちゃった。おおっ!

以下、その方法。


続きを読む "Apacheをroot権限で動かす裏ワザ"

DreamWearverソースのクリーンアップ

DreamWeaverで構築したサイトのソースが汚いので、5分くらいでクリーンアップするshを書いてみた。あとで汎用性あるように、改造するために、ここにメモ。

#!/bin/sh

echo 'remove Templates directory' rm -Rf Templates/
for FILE in `find . -name '*.html' -print` do echo ${FILE} while true do COUNT=`grep '<!-- Instance' ${FILE} | wc -l` if [ ${COUNT} -eq 0 ]; then break; fi perl -pe 's/<!-- Instance.*? -->//' ${FILE} > ${FILE}.$$ mv ${FILE}.$$ ${FILE} done done
exit

DreamWeaver自体にもソースのクリーンアップとか機能があるらしいんだけど、テンプレートから切り離したりしなくちゃいけないんで、面倒らしい。そこらへんDreamWeaver使いじゃないので、よく分からない。正攻法を調べる時間もなかったので、全部サーバに上げてもらって、shスクリプトで処理した次第。

DreamWeaverぐらいのソフトになれば、これ以上のことを、コマンド一発でやれそうな気がするのだけど。知っている人いたら、教えてくださいまし。

サイトへの全アクセスを特定ページに転送する方法

時限的なサイトの運営でよくあるのが、閉鎖時に「サイトのどのページにアクセスされても、『サービス終了のお知らせ』ページを表示させたい」という要件。具体例を出すと、

http://www.hoge.com/aaa/index.html
http://www.hoge.com/ccc/ddd/index.php

こういったHTTPリクエストに対して、常に

http://www.hoge.com/close.html

を表示させるというもの。

様々な方法があるとは思うのだけれども、個人的に常用しているのは、Apacheのmod_rewriteを使った方法。なぜ常用しているかと言うと、Apache以外のWebサーバーを運用したことが無いから。

以下、その方法。

続きを読む "サイトへの全アクセスを特定ページに転送する方法"