巡検に来ています

こんにちは。いかろです。
一ヶ月更新しないというのもあれなので書く←

実は現在清澄演習林にいます。
学科の巡検で実地の地質図をつくるというもの
基本的に鍵層となる広域に追跡可能なテフラを探しそれから断層などの構造を推定していきます.

と口で言うのは容易なのですが
テフラを同定するの大変です。

ヒルも沢山。



帰ってきたらまた細かく書きます(じゃないと月あと数分で終わってしまう...

Phusion PassengerでAliasで設定できない理由

Redmineで最初Aliasでやろうとしてコケました。なんでだろ?と思ってソースコードを追ってみた記録。

Phusion Passengerの公式サイトを見てもRailsBaseURIで設定、シンボリックリンクを張れと書いてあるのでどうやらPassenger自体の仕様のようです。
どのサイト調べてもこうしろとはかいてあるけどなんで?というのは書いてない...
だれも気にならないんだろうか?それとも常識なんだろうか?...
いずれにせよわからないのはきもちわるいのでソースコードを追ってみることにしました。

Passengerフォルダ内のext/apache2/Configuration.cppに

	AP_INIT_TAKE1("RailsBaseURI",
		(Take1Func) cmd_passenger_base_uri,
		NULL,
		OR_OPTIONS | ACCESS_CONF | RSRC_CONF,
		"Deprecated option.")

というRailsBaseURIを定義していそうな部分を見つけました。
このAP_INIT_TAKE1はマクロで第二引数にディレクティブを処理する関数のポインタが来るようです。
そこで次にcmd_passenger_base_uriの実装を探します。

cmd_passenger_base_uri(cmd_parms *cmd, void *pcfg, const char *arg) {
	DirConfig *config = (DirConfig *) pcfg;
	if (strlen(arg) == 0) {
		return "PassengerBaseURI may not be set to the empty string";
	} else if (arg[0] != '/') {
		return "PassengerBaseURI must start with a slash (/)";
	} else if (strlen(arg) > 1 && arg[strlen(arg) - 1] == '/') {
		return "PassengerBaseURI must not end with a slash (/)";
	} else {
		config->baseURIs.insert(arg);
		return NULL;
	}
}

と定義されていました。これを見てみるとDirConfig構造体のBaseURIsにパラメータを代入しています。
そこでDirConfig構造体の定義を探し見るとBaseURIsはstd::setとして定義されていました。
またコメントに「Per-directory configuration information.」とあるのでディレクトリごとの設定を保持する構造体のようです。
insertしているのでRailsBaseURIが複数回現れた場合は上書きされるのではなく追加されます。

次に実際にどう使われているのか調べてみます。
名前的にDirectoryMapper.hが怪しそうなので眺めているとDirectoryMapperというクラス内のautoDetectメソッド内に

/* Find the base URI for this web application, if any. */
const char *baseURI = findBaseURI();
if (baseURI != NULL) {
	/* We infer that the 'public' directory of the web application
	 * is document root + base URI.
	 */
	publicDir = docRoot + baseURI;
} else {
	/* No base URI directives are applicable for this request. So assume that
	 * the web application's public directory is the document root.
	 */
	publicDir = docRoot;
}

という部分がありました。Railsのpublicディレクトリを決定する動作のようです。
baseURIがnullではない場合

publicDir = docRoot + baseURI;

という処理が実行されます。
baseURIはなにが入っているか調べるためfindBaseURIメソッドの定義を見てみたところ、リクエストを解析してBaseURIの集合の中にマッチするものがあれば
それをchar*にして返すという処理をしていました。
ここでなぜAliasで設定できないかという理由がわかりました。
docRootはおそらくApacheのDocumentRootディレクティブで指定された文字列が入り、baseURIはRailsBaseURIで指定されたディレクトリがはいるのでAliasで設定されていてもpublicDirには影響を及ぼしません。
そのためRailsBaseURIで指定してあげる必要があります。
また、Aliasはリクエストが届いた際に振り分ける機能なためAliasを張ったディレクトリに対してRailsBaseURIを指定しても、
Passengerのほうはあくまで実際のファイルシステム上のフォルダを参照するためうまく働きません。
ということでシンボリックリンクをはってRailsBaseURIで指定してあげないといけません。
ということでした。

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