MySQL Connector/C++を導入してみた

MySQL Connector/C++を入れる機会があって少し悩んだのでメモ。

公式からソースコードをDLし*1makeするとmysql.hとerrmsg.hがみつからないと言われる。
ぐぐってみるとこれらはmysqlには含まれず、mysql-develに含まれるらしいので

sudo yum install mysql-devel

としてインストール。
そしてふたたび

cmake .
make clean
sudo make
sudo make install

とすることでインストールできた。
念の為動作確認を行う。(ユーザ名・パスワードは適宜変更してください。)

#include<memory>

#include<mysql_connection.h>
#include<mysql_driver.h>
#include <cppconn/resultset.h>
#include <cppconn/statement.h>

int main(){

	auto driver = sql::mysql::get_mysql_driver_instance();


	auto raw_con =driver->connect("localhost", "mysqluser", "mysqlpass");
	auto con = std::shared_ptr<sql::Connection>(raw_con);
	
	auto raw_stmt = con->createStatement();
	auto stmt = std::shared_ptr<sql::Statement>(raw_stmt);

	auto raw_res = stmt->executeQuery("SHOW DATABASES");
	auto res = std::shared_ptr<sql::ResultSet>(raw_res);

	while (res->next()) {
		std::cout << res->getString("DataBase") << std::endl;
	}

}

コンパイルは

g++ -lmysqlcppconn -std=c++0x  main.cpp

とlibmysqlcppconnの場所を教えてあげないといけない。
コンパイルできたら実行してデータベース一覧が表示されれば成功。

ちなみにMySQL Connector/C++を叩かなくてもWt::DboというORマッパーが存在するのでそちらを利用したほうが通常は捗るような気がする。

*1:ユーザ登録しなくちゃいけなかったりとひじょーにだるい。めったにDLしないからパスワードとか忘れるし...改善して欲しい

起動スクリプト(httpd)を読んでみた

シェルスクリプトの勉強がてら/etc/init.d/httpdを読んでみました。

. /etc/rc.d/init.d/functions

if [ -f /etc/sysconfig/httpd ]; then
        . /etc/sysconfig/httpd
fi

この部分で別の関数などを定義したファイルをインクルードしています。
正確には.コマンドは実行中のシェルと同じシェルで実行するというコマンドなので実行された段階で読み込まれ、他の言語で言うところのインクルードされたようにみえています。
読み込んでいる/etc/rc.d/init.d/functionsはinit.dでつかう汎用的な関数をまとめたものです。
また、/etc/sysconfig/httpdhttpdを制御するための定数を定義したファイルとなっています。(デフォルトではすべてコメントアウトされていました。)
if文ではこのファイルがあるかどうかを-f演算子でチェックし、存在すれば読み込むという処理をしています。

HTTPD_LANG=${HTTPD_LANG-"C"}

ここでは言語の設定をしています。${HTTPD_LANG-"C"}の部分はHTTPD_LANGが定義されていればその値を
されていなければ"C"を返します。
それをHTTPD_LANGに代入することでデフォルトで"C"で設定ファイルで設定されていればそっちを優先するということをしています。

INITLOG_ARGS=""

これはコメントによるとmod_sslを使う際にパスフレーズが要求されたのがlogに残るのを防ぐために設定するようです(英語自信ない...)
ただinitlogが非推奨になっていて使われていないようなのであまり関係ない部分な気がしました。

apachectl=/usr/sbin/apachectl
httpd=${HTTPD-/usr/sbin/httpd}
prog=httpd
pidfile=${PIDFILE-/var/run/httpd/httpd.pid}
lockfile=${LOCKFILE-/var/lock/subsys/httpd}
RETVAL=0
STOP_TIMEOUT=${STOP_TIMEOUT-10}

先ほどと同じようにディレクトリやファイル、タイムアウト時間などデフォルトの設定を設定しています。
これも設定ファイルで設定されていればそちらを優先します。

次にstart,stop,reroadという起動スクリプトの根幹部分の関数定義が来ます。

start() {
        echo -n $"Starting $prog: "
        LANG=$HTTPD_LANG daemon --pidfile=${pidfile} $httpd $OPTIONS
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && touch ${lockfile}
        return $RETVAL
}

start関数は名前の通り起動処理をします。

echo -n $"Starting $prog: "

echoの-nオプションは最後の改行を出力しないというオプションです。
また$""という形式になっていますがこれはこの部分が翻訳対象であることを明示しています。
翻訳データ自体は/etc/rc.d/init.d/functionのTEXTDOMAINでよみこみ先が指定されています。

LANG=$HTTPD_LANG daemon --pidfile=${pidfile} $httpd $OPTIONS
RETVAL=$?

ではhttpd本体をdaemon関数(/etc/rc.d/init.d/function)を用いてデーモンとして起動しています。
また、--pidfileオプションでPIDファイルの出力先を決めています。また最初のLANGの部分でhttpdを起動する言語を指定しています。
またRETVALはreturn valueの略語のようでそのとおり$?で前のコマンドの終了コードを代入しています。

echo
[ $RETVAL = 0 ] && touch ${lockfile}

つぎにechoで改行を入れ、そのあとの部分でRETVALが0ならばロックファイルを生成する(orタイムスタンプを更新)という処理をしています。
ロックファイルは起動スクリプト内のどこにも存在をチェックしている部分がないのでおそらくhttpd内部で処理をしている気がします。

stop() {
        echo -n $"Stopping $prog: "
        killproc -p ${pidfile} -d ${STOP_TIMEOUT} $httpd
        RETVAL=$?
        echo
        [ $RETVAL = 0 ] && rm -f ${lockfile} ${pidfile}
}

次はhttpdを停止するstop関数です。
基本的な流れとしてはstopしていることを表示し、killprocによってプロセスを殺します。
そして正常に殺せた場合はlockfileとpidfileを削除します。

reload() {
    echo -n $"Reloading $prog: "
    if ! LANG=$HTTPD_LANG $httpd $OPTIONS -t >&/dev/null; then
        RETVAL=6
        echo $"not reloading due to configuration syntax error"
        failure $"not reloading $httpd due to configuration syntax error"
    else
        # Force LSB behaviour from killproc
        LSB=1 killproc -p ${pidfile} $httpd -HUP
        RETVAL=$?
        if [ $RETVAL -eq 7 ]; then
            failure $"httpd shutdown"
        fi
    fi
    echo
}

つぎは設定ファイルを読み込むreload関数です。

if ! LANG=$HTTPD_LANG $httpd $OPTIONS -t >&/dev/null; then

の部分ではhttpdを-tオプションをつけ実行して結果を捨てています。

  • tオプションをつけると文法チェックをしてくれるのでこのif文では

文法エラーがあったらthenの部分を実行します(!で結果を反転させているため)

RETVAL=6
echo $"not reloading due to configuration syntax error"
failure $"not reloading $httpd due to configuration syntax error"

の部分を実行します。この部分では返り値を6とし文法エラーがある旨を出力します。
文法エラーがなかった場合

LSB=1 killproc -p ${pidfile} $httpd -HUP
RETVAL=$?
if [ $RETVAL -eq 7 ]; then
    failure $"httpd shutdown"

の部分でkillprocによりhttpdにHUPシグナル(子プロセスは殺すが、親プロセスは殺さない)が送られます。
そしてその結果を見て成功かどうかを表示します。

関数の定義が終わると引数によるパターンマッチを行なって適切な関数へのディスパッチをおこなう処理に入ります。

case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status -p ${pidfile} $httpd
        RETVAL=$?
        ;;
  restart)
        stop
        start
        ;;
  condrestart|try-restart)
        if status -p ${pidfile} $httpd >&/dev/null; then
                stop
                start
        fi
        ;;
  force-reload|reload)
        reload
        ;;
  graceful|help|configtest|fullstatus)
        $apachectl $@
        RETVAL=$?
        ;;
  *)
        echo $"Usage: $prog {start|stop|restart|condrestart|try-restart|force-reload|reload|status|fullstatus|graceful|help|configtest}"
        RETVAL=2
esac

第一引数でパターンマッチを行なっています。start,restart,reload(force-reload)は基本的に先ほど定義した関数を組み合わせているだけです。
condrestartはプログラムが実行中であるかどうかを判定して実行中である場合のみ再起動、gracefulはapachectlに丸投げしています。
また、それ以外の場合はマッチするものがなかった旨を表示します。

最後に

exit $RETVAL

として終了します。

bashはすごく奥が深そうです...

さくらVPSでKernel再構築

最近サーバ関係の記事が多いですね。実はインフラエンジニアのバイトをはじめまして鯖触るようになって色々と勉強してます。

さて、ふと見たら昨日LinuxのKernel3.9.5(stable)がでてたのでさくらVPSにいれてみることにしました。
面倒なのでrootで作業しちゃいます(良くないですね
とりあえずソース・コードの入手。展開。

#wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.9.5.tar.xz
#tar Jxvf linux-3.9.4.tar.xz 

tarで一応一覧表示してますが、べつにいいやって場合はvオプション外してもいいかもしれません。(一応出力しといたほうがなんかあったとき便利かなと思うけどこれに関しては今のところ使ったことないし...)

さて、一から設定するのも面倒なので現在のカーネルの設定を基本的に引き継いでコンパイルします。

#uname -r
2.6.32-358.6.1.el6.x86_64
#cp /boot/config-2.6.32-358.6.1.el6.x86_64  ./config
#make oldconfig

これのunameでは現在のカーネルを表示しています。私の環境では2.6.32-358.6.1.el6.x86_64でした。これをコピーします。
そしてoldconfigオプションを付けてコンパイル。これで現在の設定を引き継いでコンパイルしてくれます。
色々と聞かれるので答えていきましょう。ちなみにわたしは途中でつかれてEnter押しっぱなしにしてましたw(というわけであんまりkernelをビルドする必要性がない感じ...)
READMEをよむと新しく追加された項目だけ質問してくれるsilentoldconfig、新しい項目はデフォルトのにしてあとは設定ファイルに従ってしてくれるolddefconfigなんてオプションがあるのでそっちをつかったほうが良かったのかもしれません。
あとはmakeしてインストールします。このときmake modules_installを実行する前に以前のkernelのbackupをしといたほうがいいよって書かれているので気になる人はしときましょう。

make
make modules_install
make install

という感じでとりあえずおわりました。

次にbootローダでデフォルトで起動するように設定します。下の方に3.9.5のkernelがあるのでそれが何番目かを数えて/boot/grub/menu.lstの中にdefault=数字って部分を変更します。この時0から数えることに注意してください。(わたしの環境では0番でした。普通にすれば一番先頭に追記される気がします)
これであとはrebootします。しばらくまってからsshでつなぎuname -rとすると3.9.5と表示され確かに更新されていることがわかります。
案外すんなりできてしまいましたね。次するときはオプションもしっかり指定できるようになりたい...

グリーン関数の導出

物理やってるとグリーン関数なるものがよく登場しますね。
ポアソン方程式
\nabla^2 \phi =- \frac{\rho}{\epsilon_0}
のような方程式を解くときに使うあれです。

ただ解けはするんだけどなんか気持ち悪いなーとか思っていて、パルスって説明もちょっと納得いかず色々とこねくり回してたらそれっぽい感じの説明思いついたので書いておきます。(正しいかは保証しません)

方程式
\mathcal{L} \phi = f
\phiについて解くことを考えます。ここで\mathcal{L}微分を含むような線形作用素だとします。
行列とベクトルみたいな感じで両辺から\mathcal{L}の逆作用素をかけてあげると
\mathcal{L}^{-1}\mathcal{L} \phi = \mathcal{L}^{-1}f
 \phi = \mathcal{L}^{-1}f
となり、形式的には\phiが求まりました。が、逆作用素の実体が不明なのでこれを求めます。
微分の逆演算なので積分になりそうです。とりあえず以下のように仮定してみましょう。
 \mathcal{L}^{-1} \psi = \int G(x-x') \phi(x') dx'
積分になるだろうという予測、そしてたんなる積分ではなくなにか関数Gも含むだろうという予測です。
あとはGをもとめればいいだけ(存在するのかというのもホントは証明しないといけないですけど)ということですが、
積分が含まれていて余計にややこしくなったように見えます。
今Gを積分から取り出すのにデルタ関数を用います。
\phi = \delta(x)
とおいて代入してみましょう。
 \mathcal{L}^{-1} \delta(x) = \int G(x-x') \delta(x') dx'
 \mathcal{L}^{-1}  \delta(x) = - G(x)
めでたく積分の中からGを取り出せましたね。
 \mathcal{L}^{-1}  \delta(x) =  -G(x)
あとは\mathcal{L}を両辺にかけて
 \delta(x) = - \mathcal{L}G(x)
\mathcal{L}G(x) = - \delta(x)
という方程式をとけば良いだけです。ポアソン方程式の場合はフーリエ変換して逆変換してあげれば出ますね。
この方程式に出てきたGのことをグリーン関数と呼びます。

Apache2.4ではまった話(cgiモジュールとhtpasswd)[メモ]

apache2.4つかってて
1.デフォルトでcgid_moduleがオフになっている。
2.Apache2.4.4のhtpasswdが正常に動かない(バグが有る)
というのにはまった。ということでメモ。


1.デフォルトでcgiモジュールがオフになっている。
cgiがうごかなくて
AddHander cgi-script
とかしても動かず悩んでいたところしらべたら
LoadModule cgid_module modules/mod_cgid.so
がどうやらコメントアウトされているらしい。ということでコメントアウトを解除したら動いた。2.2系だと標準でonになっていたのでまったくきづかなかった。セキュリティ上安全になったということなんだろうけどこういう変更辛い...


2.Apache2.4.4のhtpasswdが正常に動かない(バグが有る)
Apache2.4.4のhtpasswdにはバグがあってうまくパスワードファイルを生成できない。まあ、BASIC認証なんて危険だから使うなよという話はおいておいて(ローカルネットワークだと手軽にできるし)
修正方法としてはソース・コードを展開したディレクトリのsupport/passwd_common.cを書き換えてビルドしなおしてあげればよい。168行目辺りに

pw = pwin;

という部分があるのでこの前に

strcpy(pwin,ctx->out);
pw = pwin;

というふうに追記してやれば良い。
もとのコードではその前の get_password(ctx)という部分でパスワードをctxのoutメンバに書き込んでいるらしいのだがなぜかそれを使わずにpwinをpwに代入している。おそらくこれはpwinにoutの内容を書き込んでからこうする予定だったのだろうなということでstrcpyでpwinに書き込んでやる。そうすればちゃんとうごくというわけ。きっともともとこういうことを想定していたんでしょう。

参考:
http://d.hatena.ne.jp/rougeref/touch/20120521#1337587242
http://apache24.jugem.jp/?eid=7

Apache2.4.4をソースから導入するときのメモ

Apache2.4.4をソースから入れる機会があって色々と躓いたのでメモ。

作業の大まかな流れとしては

という感じでおこなった。

まずは以下の場所からソースコードをダウンロードし展開する。

wget http://ftp.riken.jp/net/apache//httpd/httpd-2.4.4.tar.gz
tar xfvz httpd-2.4.4.tar.gz

次にMAKEFILEを生成するために

./configure

としたところ

apache2 apr not found

というエラーが出た。
そこで

cd httpd-2.4.4/srclib
wget http://ftp.riken.jp/net/apache//apr/apr-util-1.5.2.tar.gz
wget http://ftp.riken.jp/net/apache//apr/apr-1.4.6.tar.gz

としてダウンロード。

tar xfvz apr-1.4.6.tar.gz
tar xfvz apr-util-1.5.2.tar.gz 
mv apr-1.4.6 apr
mv apr-util-1.5.2 apr-util

としてそれを展開してそれぞれaprとapr-utilとリネーム。
その後ふたたびapacheのディレクトリに戻り

./configure

これでうまくいくかとおもいきや今度は

pcre-config for libpcre not found

というエラーが出るので

wget "http://sourceforge.jp/frs/g_redir.php?m=jaist&f=%2Fpcre%2Fpcre%2F8.32%2Fpcre-8.32.tar.gz"
tar xvzf pcre-8.32.tar.gz
cd pcre-8.32
./configure
make
make install

としてPCREを導入した。
ここで気をつけなくてはいけないのは""で囲むこと。そうじゃないとうまくDLされない...

その後apacheのディレクトリにはいり再び

./configure

とすると
うまく通ったので

make
make install

Apacheをインストールした。

次にapacheを起動するため

/usr/local/apache2/bin/apachectl start

すると

AH00558: httpd.exe: Could not reliably determine the server's fully qualified domain name, using fe80::1155:696f:bc0c:6ebd. Set the 'ServerName' directive globally to suppress this message

というエラーがでたので

vi /usr/local/apache2/conf/httpd.conf

ServerName <サーバのIPAdress>:80

という行を追加。
これでエラーはでなくなったが、リモートのブラウザからはアクセスできない。
そこできちんと動いているか確認するためサーバ側で

wget http://<サーバのIPAdress>

とするとindex.htmlが正常にダウンロードされる。
ここでしばらくなやんが、
色々と調べた結果80番のポートが開放されていないようなので

/etc/sysconfig/iptables

を見てみるとたしかに80番のポートが開放されていない。(逆に最初から開放されていても怖いが、いままでクライアントとして使ってなかったので全然意識してなかった)
そこで

-A INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT

という行を追記し、

/etc/init.d/iptables restart
/usr/local/apache2/bin/apachectl restart

によって再起動をかけてクライアントのブラウザからアクセスすると「It Works!」という表示が見ることができた。

Oauth認証で非常につまらないところで躓いた話(Oauthとタイムスタンプ)

昨日からふと思いたちPythonのtweepyを使ってtwitterで色々と遊んでる。そのときStreamingAPI使うと常に401が帰ってきてしまった。どうやら認証で弾かれているらしいということなのだが...tweepyのソース読んだり、色々と調べてみたが解決しない。いっそのこと自分で実装するか?とか考え始めた時ふとPCの時計に目をやると時刻がずれている...もしや?と思い直して試してみるとすんなり動いてしまった。こんなくだらないことだったとは...とはいえ私みたいに躓いて悩む人がいるかもしれないので一応メモとして残しておく。
 ちなみにしらべてみるとOauthで送られる情報には時刻(タイムスタンプ)が含まれていて一定以上のずれがあるとはじかれる模様。ライブラリ使うとしても完全にブラックボックスで使うのは良くないですね。