起動スクリプト(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/httpdはhttpdを制御するための定数を定義したファイルとなっています。(デフォルトではすべてコメントアウトされていました。)
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はすごく奥が深そうです...