SHELLのコマンド履歴検索を便利にしよう

先日、FreeBSDを久しぶりにいじった際に便利な機能を思い出しました。
上下キーによるコマンド履歴なのですが、プロンプトに入力した文字列をもとに絞り込んで履歴を検索できるため非常に便利です。

設定方法

ここでは、tcsh/bash/zshでそれぞれ同じ機能を利用するための「キーバインド」です。
※動作は確認していますが、詳細については調べきれていないのでご容赦を...

tcshの場合

bindkey -k up history-search-backward
bindkey -k down history-search-forward
※コマンドとして実行しても利用可能ですが、セッションごとにクリアされるため、永続的に利用する場合~/.tcshrcなどに記述すると良いでしょう。

bashの場合

~/.inputrcに以下の行を追加します。有効にするには再度ログインし直すか、ctl+x ctl+rを実行を入力してください。

"\e[A":history-search-backward
"\e[B":history-search-forward

zshの場合

bindkey "^[[A" history-beginning-search-backward
bindkey "^[[B" history-beginning-search-forward
tcshと同様のため、永続的に利用する場合は~/.zshrcなどに記述すると良いでしょう。

以上。

xdebug+Eclipse+PDTで幸せ開発環境

久しぶりにPHPによる開発を目の当たりし、ステップ実行でデバッグできないのは難儀だなぁと、
xdebugによるデバッグ環境構築を試してみました。

自分が開発していたときを思い出すと、「perlではステップ実行できるのにphpだと出来ないな」
などとぼやきながらviでトライ&エラーでデバックコードを埋め込んでいた記憶があります。

とりあえず、開発環境を構築しよう。

XAMPやMAMPなど、クライアントPCで動かすPHP環境には導入と同時にxdebugがインストール
されているようですが、ここではあえて下図のようなリモートサーバでの開発を念頭に話を
進めていきます。

CentOSを開発サーバとしてxdebugを導入する

LAN上に開発サーバをおくことを前提として、selinuxiptablesを停止します。

# setenfoce 0
# chkconfig iptables off
# chkconfig ip6tables off
# service iptables stop
# service ip6tables stop

手軽にyumでサーバ構築を行うため、remiリポジトリを登録します
# rpm -Uvh http://dl.fedoraproject.org/pub/epel/6/i386/epel-release-6-7.noarch.rpm
# rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

続いて、Apache+PHPの環境を構築します。
# yum install -y httpd.x86_64 httpd-devel.x86_64
# yum install -y \
            php.x86_64 \
            php-mbstring.x86_64 \
            php-pear.noarch \
            php-devel.x87_64
※試験的な環境のため、その他必要なモジュールがあれば一緒にインストールしてください。
xdebugpeclモジュールをインストールします。
# yum install -y php-pecl-xdebug.x86_64
xdebugを設定する
インストール直後のままではリモートデバッグが行えないため、設定ファイルを修正します。
# vi /etc/php.d/xdebug.ini
; Enable xdebug extension module
zend_extension=/usr/lib64/php/modules/xdebug.so
xdebug.remote_enable = On
xdebug.remote_connect_back=On
xdebugの設定パラメタはphpinfo();をみていただければわかりますが色々とありますが、
ここでは最低限の情報のみ記述いたします。
xdebug.remote_connect_back=On
デフォルト値ではこの値はOffとなっており、xdebugによるデバッグ情報のやり取りは
xdebug.remote_host”で設定されたホストに限定されます(default:localhost)。

単一ホストを指定する場合、この値に対象のIPアドレス指定すれば良いのですが、
接続元IPが明示的に指定できない場合などでは、xdebug.remote_connect_backを
有効にすることで、リクエスト元とxdebugを疎通させます。

xdebugIDE間の情報伝達の流れ

どのように、xdebugが動作するかについては、オフィシャルドキュメント
「Communication Set-up」をご覧いただきたいと思いますが、
簡単に説明すると、

おまけ。Sambaを設定する

yumからsambaサーバをインストールします。

yum install -y samba.x86_64

ここでは、とりあえず設定しているので以下のような感じで設定ファイルを準備しています。
# vi /etc/samba/smb.conf
[global]
        workgroup = MYGROUP
        server string = Samba Server Version %v
		
		log file = /var/log/samba/log.%m
		max log size = 50
		
		security = user
        passdb backend = tdbsam
        map to guest = Bad User

[developments]
        comment = Developmentsp
        path = /var/www/html
        public = yes
        guest ok = yes
        writable = yes
        printable = no

samba経由でファイルの書き込みはnobodyで行われるため、共有対象パスの
パーミッションを変更します。
# chown nobody:nobody /var/www/html

とりあえず、以上です。 Eclipse側の設定については改めて記載したいと思います。

第4弾 チューニンガソンに参加してきた

7/1(日)、ゼロスタートさんの主催するインフラチューニングのイベント「チューニンガソン」に参加してきました。
チューニンガソンとは、アプリ以外のインフラ部分だけをチューニングしてレスポンス速度を競うバトルです。


結果的にはとりあえず、7位に入賞することができました。

今回のお題は?

お題はバトル開始直前に発表されます。今回はAWSにインストールされた"refinery"というRuby on Railsで書かれた
CMSのレスポンスを競うというものでした。

バトル条件
  • RoR refineryのコメントPOST/GET回数
  • 10並列で一定秒数間測定
  • 秒間平均POST/GET回数がスコア
  • エラー返却は単純に除外
  • POSTはGETの10倍のスコア
  • POST後のGETによる反映チェック
  • 反映チェックの成功率の二乗をスコアに乗算

早速チューニング開始

正直なところ、RoRなんてRedmineの構築程度しか触ったことが無かったため何をチューニングすれば良いか
さっぱり検討もつかず、途方にくれつつのチューニングとなりました。
ありがたいことに、当日の持ち物に「諦めない気持ち」が入っていたためなんとか乗り切ることができましたw

チューニング内容


REE(Ruby Enterprise Editon)の導入については、Redmineインストール時にREEを利用した方が効率的との
記事をみていたため、早速導入してみました。
http://blog.redmine.jp/articles/redmine-2_0-installation_centos/:titile
http://hiroki.jp/2011/01/09/1374/
もちろん、最新版Rubyの導入を検討しなかった訳ではないのですが、gemとライブラリのバージョン問題に
悩まされたくなかったので、チューニング環境と同バージョンであるREEを選択した訳です。

結果として、若干スコアの向上が見受けられました。
また、mysqldのreniceについては前回のチューニンガソンで効果が得られるとのことで、おまじない的に
採用してみました。効果的にはあったのか無かったのかいまいち判断できず。

Passenger導入でスコアが劇的に変化

上記チューニングで、多少の効果はみられましたがその後は頭打ち。

チューニング開始前

Score: 2.483 (get=1.400, comment=1.083(2), check=1.000)

REE+mysqldのrenice後
Score: 3.483 (get=1.900, comment=1.583(2), check=1.000)

とりあえず、修正可能なRoRの設定ファイルでのチューニングを試みましたが、にわか知識では
チューニング方法がいまいち理解できず、足止め状態になってしまいました。

公式計測開始まであと20分と差し迫ってきたため、とりあえずPassengerを導入。
計測してみると、Scoreがだいたい13〜15をキープするようになりました。

公式計測では、予想以上に高く「17.41」。
わからないながらのチューニングでしたが、本当に運が良かったです。

上位入賞者との比較。

今回のイベントで、1位・2位をとられた方々は堂々の4桁スコア。
チューニング内容を伺うと、varnishを利用されたとか。
HTTPアクセラレータの存在は偉大だと実感しました。

今回利用したAMI(Amazon Machine Image)が公開されているそうですので、
時間を見つけてvarnishも試してみたいと思います。

ami-64145536

最後に

こんな面白いイベント、末永く続けていただきたいです。

  • 会場を提供くださった、VOYAGE GROUPさん
  • AWSの提供をして頂いているAmazonさん、
  • 取材にいらした技術評論社さん
  • 運営をして頂いているゼロスタートさん

今後ともよろしくお願いいたしますm(_ _)m

SSL(Secure Socket Layer)とはなにか

先日、SSL通信とはどういうものかと教える機会があったのですが、
意外とうまく説明出来なかったため、簡単にまとめて見ました。

SSLとは何者か?

"SSL(Secure Socket Layer)"を一言で言うと暗号化通信を行うための
通信プロトコルです。
OSI参照モデルではセッション層とトランスポート層の間で動作しており、
Netscape Communications社により規定されましたが、現在ではRFC2246や
RFC4346などでTSL(Transport Layer Security)として標準化されています。

規約の詳細を理解することは大事な事ですが、今回は少しライトな感じに
まとめてみたいと思います。

暗号化通信の仕組み

SSL/TSLでの暗号化通信は、公開鍵(Public Key)・秘密鍵(Private Key)・
共通鍵(Secret Key)の3つの鍵によってとり行われます。

1. WebブラウザよりSSL通信をサーバに要求
2. 署名付き証明書とサーバ公開鍵を送付
3. 共有鍵をランダムに生成し、共有鍵をサーバの公開鍵で暗号化して送付
4. 共通鍵により暗号化通信を開始

SSL/TSL通信では、サーバは不特定多数のクライアントと暗号化通信を行う
必要に迫られているため、通信相手が公開鍵暗号方式のようにキーペアを
所持しているとは想定できません。そこで公開鍵を利用して共通鍵を送付し、
共通鍵による暗号化通信を行います。

忘れてはいけない第三者認証

SSL/TSLを語る上で忘れていけないのがPKI(Public Key Infrastructure)です。
読んで字のごとく、日本語では公開鍵基盤と呼ばれておりますが、公開鍵の
持ち主を証明するための基盤を提供します。
SSL暗号通信について言えば、PKIよりもCA(Certification Authority:認証局)
といったほうが馴染み深いのではないでしょうか?

先にも説明したとおり、SSL/TSL通信ではサーバ公開鍵で暗号化された共有鍵を
使って暗号化通信を行うため、公開鍵が正規のサーバから発行された鍵である
ことが証明できない限りは正しい相手と通信している保証が取れません。

そこで、第三者から公開鍵に署名付き証明書を付加してもらうことで正当性を
与える必要性があります。

"jsvc"でTomcatをデーモンとして起動する

久しぶりにTomcatをインストールした際、jsvcコマンドの名前を思い出せなかったため備忘録。

jsvc(commons-daemon)でTomcatをデーモン起動

以前は、Tomcatの起動にstartup.sh/shutdown.shをrcスクリプトから呼び出していましたが、 ドキュメントの"Setup"にはjsvc(commons-daemon)が紹介されています。

Tomcat can be run as a daemon using the jsvc tool from the commons-daemon project.

jsvcを利用するメリットは、直接Tomcat(org.apache.catalina.startup.Bootstrap)を 制御(起動・停止)できるため、シンプルな設計になることです。

commons-daemonコンパイルする

先ほどメリットを説明しましたが、デメリットもあります。それはソースで配布されているため 自身でコンパイルする作業が必要になることです。とはいっても非常に簡単にコンパイルできます。

コンパイルに必要な環境は、gcc、gmake、autoconf、そしてJDKになります。

# yum install gcc make autoconf
JDKは使用するJavaによって変わりますが、ここではSun Java SE6 update27をインストールしました。
Download: Java SE - Downloads | Oracle Technology Network | Oracle
# chmod +x jdk-6u27-linux-x64-rpm.bin
# ./jdk-6u27-linux-x64-rpm.bin
# export JAVA_HOME=/usr/java/default

続いて、Tomcatを展開します。ここでは、Tomcat 6.0.33を使用しました。
# tar xvzf apache-tomcat-6.0.33.tar.gz
# mkdir -p /opt/apps
# mv ./apache-tomcat-6.0.33 /opt/apps/
# cd /opt/apps
# ln -s apache-tomcat-6.0.33 tomcat6

Tomcat6には、"commons-daemon-native.tar.gz"というファイル名でcommons-daemonのソースが添付されています。
# cd /opt/tomcat6/bin
# tar xvzf commons-daemon-native.tar.gz
# cd /opt/apps/tomcat6/bin/commons-daemon-1.0.7-native-src/unix
# ./configure
# make
# cp jsvc ../..

以上で、コンパイルと配置は完了です。

rcスクリプト

/etc/init.dにrcスクリプトを作成します。
なお、内容はソースディレクトリにある"sample/tomcat5.sh"を参考にCentOS5用に作成しました。
# cd /etc/init.d
# vi tomcat6
#!/bin/sh
# chkconfig: - 80 20
# description: tomcat6
# Source function library.
. /etc/init.d/functions

JAVA_HOME=/usr/java/default
CATALINA_HOME=/opt/apps/tomcat6
DAEMON=$CATALINA_HOME/bin/jsvc
TOMCAT_USER=root

# for multi instances adapt those lines.
TMP_DIR=/var/tmp
PID_FILE=/var/run/tomcat.pid
CATALINA_BASE=$CATALINA_HOME
LOCKFILE=/var/lock/subsys/tomcat

CATALINA_OPTS=
CLASSPATH=\
$JAVA_HOME/lib/tools.jar:\
$CATALINA_HOME/bin/commons-daemon.jar:\
$CATALINA_HOME/bin/bootstrap.jar

start() {
        #
        # Start Tomcat
        #
        echo -n "Starting Tomcat: "
        $DAEMON $JSVC_OPTS \
        -user $TOMCAT_USER \
        -home $JAVA_HOME \
        -Dcatalina.home=$CATALINA_HOME \
        -Dcatalina.base=$CATALINA_BASE \
        -Djava.io.tmpdir=$TMP_DIR \
        -wait 10 \
        -pidfile $PID_FILE \
        -outfile $CATALINA_HOME/logs/catalina.out \
        -errfile '&1' \
        $CATALINA_OPTS \
        -cp $CLASSPATH \
        org.apache.catalina.startup.Bootstrap
        #
        # To get a verbose JVM
        #-verbose \
        # To get a debug of jsvc.
        #-debug \
        RETVAL=$?
        if [ $RETVAL = 0 ]; then
                echo_success
                touch $LOCKFILE
        else
                echo_failure
        fi
        echo
}

stop() {
        #
        # Stop Tomcat
        #
        echo -n "Shutting Down Tomcat: "
        $DAEMON $JSVC_OPTS \
        -stop \
        -pidfile $PID_FILE \
        org.apache.catalina.startup.Bootstrap
        RETVAL=$?
        if [ $RETVAL = 0 ]; then
                echo_success
                rm -f $PIDFILE $LOCKFILE
        else
                 echo_failure
        fi
        echo
}

case "$1" in
        start)
                start
                ;;
        stop)
                stop
                ;;
        restart)
                stop
                start
                ;;
        status)
                status $DAEMON
                RETVAL=$?
                ;;
        *)
                echo $"Usage: $0 {start|stop|restart|status}"
                exit 1
                ;;
esac

rcスクリプトを作成したら、サービス登録しOS起動時に自動起動するよう設定します。
# chkconfig --add tomcat6
# chkconfig tomcat6 on
# service tomcat6 start

コンパイル時にちょっとハマッた件

今回、OSはCentOS5.5 64bit版(CentOS-5.5-x86_64)を使用したのですが、jsvcを実行すると

jsvc error: Cannot find any VM in Java Home /usr/java/default
なるエラーメッセージが発生し、Tomcatを立ち上げることができませんでした。

原因は、誤って32bit版のJDKをインストールしてしまっていたためでした。 64bit版のJDKを入れなおすことによって回避できます。
参考:http://comments.gmane.org/gmane.comp.jakarta.tomcat.user/206762

以上。

UbuntuにWindowsXPからリモートデスクトップ接続

ふと、Linuxリモートデスクトップ(RDP:Remote Desktop Protocol)接続できないかと
調べてみたところ、xrdpというツールがあったので試してみた。
ProjectPage:xrdp by neutrinolabs

Ubuntu11.04へインストールしてみる

とりあえず利用してみたいと思ったので、手元のUbuntu11.04マシンでパッケージの
有無を調べてみた。

$ sudo apt-cache search xrdp
xrdp - Remote Desktop Protocol (RDP) server

パッケージ発見。あくまでとりあえずなので考えなしにインストール&利用してみる。
$ sudo apt-get install xrdp -y

インストール完了後、いつものとおり自動でサービスが起動されるので、
クライアントのWindowsXPからリモートデスクトップ接続してみる。

WindowsXPから「ファイル名を指定して実行」から、mstscを実行


リモートデスクトップ接続画面


なお、私が使っているGNOME環境でリモートデスクトップ経由で「D」の文字を
入力するとデスクトップが表示されるという不可解な現象に見舞われました。
調べてみると、GNOMEの設定で"d"のキーストロークが"show_desktop"に
割り当てられていることが原因のようです。

gconf-editorより、"show_desktop"のキーバインド変更することで対処できます。
1) Alt+F2 でアプリケーションの実行ダイアログを開く
2) gconf-editor を実行
3) / -> apps -> metacity -> global_keybindings を実行
4) show_desktop に割り当てられたキーストロークを "d" から "d", "d" または "disabled" に変更する。
参考ページ:Ubuntu日本語フォーラム / xrdpのショートカットキー

設定などの詳細は、改めて調べてみたいと思う。

以上。

KVMのGuestOS上でCPUの仮想化支援技術を利用する

通常、CPUの仮想化支援機能を利用(認識)できるのは、ハイパーバイザまでですが、
KVMのNestedを使うことでGuestOS上でも仮想化支援機能を利用できるようになります。
要は、『KVM on KVM』などというトリッキーな遊びができるわけです。

実際どれほど有用な機能なのか語ることは難しいのですが、個人的には複数の
物理マシンを保有できないため、ライブマイグレーションの実験やらプライベート
クラウドの実験環境やらで活躍しています。

ハードウェアの制約

今回、この記事を書くために改めて調べてみましたが、未だIntel系のCPUでの対応は
不完全のようです。(Kernel Patchは存在するようですが...)
このため、気軽に試すのであればAMD(AMD-V)のCPUである必要があります。

設定手順

ここでは、手軽なLinuxディストリビューションであるUbuntu Server 11.04で構築する
手順を記します。
KVM環境のインストールについてはSettingup LinuxKVM - La vie des marmotteをご覧ください。

■Kernel module "kvm_amd"のnestedオプションを有効にする

$ sudo /etc/init.d/libvirt-bin stop
$ sudo modprobe -r kvm_amd
$ sudo modprobe kvm_amd nested=1
OSの再起動毎に再設定する必要が生じるため、設定ファイルを修正します。
$ sudo vi /etc/modprobe.d/kvm.conf
--
options kvm_amd nested=1
--

仮想マシンの起動
KVM仮想マシンを起動する場合、"kvm"コマンドにて起動させますがこのまま起動しても
GuestOS上で仮想化支援機能を利用することができません。
実際には、"kvm"コマンドは"qemu-system-x86_64"コマンドのシンボリックリンクで、
オプションを確認すると次のようなオプションが存在します。
$ qemu-system-x86_64 --help | grep nest
-enable-nesting enable support for running a VM inside the VM (AMD only)

virt-managerを利用してGuestOSを管理したいときなど、"kvm"コマンドを裏で実行している
ため、専用のシェルスクリプトを作成しておくと便利です。
$ sudo vi kvm-nested
--
#!/bin/bash
exec /usr/bin/qemu-system-x86_64 -enable-nesting "$@"
--
$ sudo chmod +x kvm-nested

また、Ubuntu11.04ではAppArmorによってセキュリティ管理されているため設定を追加します。
$ sudo vi /etc/apparmor.d/abstractions/libvirt-qemu
--
/usr/bin/kvm-nested rmix,
--

最後に、必要に応じてkvmコマンドのシンボリックリンクを書き換えます
$ cd /usr/bin
$ sudo mv kvm kvm.org
$ sudo ln -s /usr/bin/kvm-nested /usr/bin/kvm

以上

参考資料:HugeDomains.com - Shop for over 300,000 Premium Domains