読者です 読者をやめる 読者になる 読者になる

萬由無事覚書

不知物故萬由無事覚書仕候也。

Gentoo Linux (OpenRC) でinitスクリプトを書くには [基本編]

何かの機能を提供するシステムを構成する時、OSのパッケージ管理システムに必要なサービスが含まれていなくて、手動でインストールしないといけない場合がある。

その場合、困るのが「再起動時の自動起動」。手動でやってると、メンテナンスで再起動なんかした時に、つい忘れてしまうんだよね。

ここは精神の安定とシステムの平和を守るためにも、自動にしておきたいところ。

Gentoo (正確にはOpenRCをinitシステムとして使っている場合のみだけど ) では、initスクリプト (起動スクリプト) を用意してやることで、サービスや開始や停止、自動起動の登録などの制御ができるようになる。

これは、サービス (デーモン) を自作するときにも役に立つ。例えばWebアプリを稼働させる場合、キャッシュサーバ、Webサーバ、アプリサーバ、DBサーバなどが相互に依存して絡み合いながら動作するので、適切な起動順で各サービスを自動起動させるのは、運用上、結構重要だ。

というわけで、今回はOpenRCにおけるinitスクリプトの基本をメモメモ。

サービスの基本

ここらへんは簡単に。hogehogeがサービス名ね。

起動
/etc/init.d/hogehoge start
停止
/etc/init.d/hogehoge stop
再起動
/etc/init.d/hogehoge restart
説明の表示
/etc/init.d/hogehoge describe

一般的なサービスの起動と終了の方法に同じです。

これらのコマンドを指定して起動すると、対応するスクリプトコードが実行されることになる。

全体のレイアウトと保存先

まずはinitスクリプトの全体像を見てみる。

#! /sbin/runscript

depend() {
  依存関係の設定に必要な処理
}

start() {
  開始時に必要な処理
  startコマンドで実行される
}

stop() {
  停止時に必要な処理
  stopコマンドで実行される
}

見ての通り、サービスの開始と停止、依存関係を設定している。

この内容のファイルを作り、編集して/etc/init.dに保存する。こんなかんじ。

# touch /etc/init.d/hogehoge
# nano /etc/init.d/hogehoge
# chmod 755 /etc/init.d/hogehoge 

実行属性を忘れないこと。hogehogeサービス名で、自動起動や依存関係などの設定をするときに使う。

文法

とっても簡単。

  • 基本はBシェル系のシェルスクリプト
  • なのでコメント、変数、関数などの形式も同様。
  • initスクリプトの中だけで使える特殊なコマンドがある。

つまり、シェルスクリプトを書いたことがあれば、まったく問題なくinitスクリプトを書けるってことだ。

依存関係の設定

サービス間の依存関係を設定しておくことで、サービスの起動順序を制御できる。

依存関係は、depend()関数の中に書く。

depend() {
  need net
  use logger
}

ここでneedとかuseってのがでてきた。

これは、依存性を設定するコマンド。

use service 絶対に必要なわけではないけど、あるとより多くの機能が使えるようになるようなサービスが有る場合、そのサービス名を指定する。ロガーなんかが該当する。具体的なサービスでもいいし、仮想サービスでもいい。
need service 絶対に必要なサービスの名前。ないと起動できないもの。具体的なサービスでもいいし、仮想サービスでもいい。
before service 同じinitレベルでserviceが自動起動する場合に限り、serviceより先に起動するようにする。
after service 同じinitレベルでserviceが自動起動する場合に限り、serviceより後に起動するようにする。beforeの反対。
provide service 仮想サービスを提供する。
config file fileが更新された場合、依存関係に基づく起動順序を再計算する。

仮想サービス

ここで、仮想サービスについて簡単にメモメモ。

仮想サービスは、ある機能を提供するサービスが複数ある時に、そのどれでもOKな場合に利用する機能。例えば、syslog-ng、metalog、sysklogdなどは、同じ仮想サービスloggerを提供する。

有名どころとしては、loggercronnetなど。

使える一覧は、こんなかんじで取得するといいかも。

# cd /etc/init.d
# grep "^[[:space:]]*provide " *

開始

サービスを開始する時のコマンドは、start()関数の中に書く。

start() {
  ebegin "Starting Apache"
  apachectl start
  eend $?
}

ここではApache HTTP Serverを例にしている*1

ehogehoge形式のコマンドは、initスクリプトの中だけで使えるコマンド。とりあえず基本編では、次の5つをピックアップ。

einfo [message] messageを表示する。情報提供用。この時、先頭には緑色の「*」が付く。
ewarn [message] messageを表示する。警告表示用。この時、先頭には黄色の「*」が付く。
eerror [message] messageを表示する。エラー表示用。この時、先頭には赤色の「*」が付く。
ebegin [message] messageを表示する。起動メッセージ用。この時、先頭には緑色の「*」が付き、末尾には「...」が付く。
eend retval [message] retvalが0でなければ、エラーメッセージとしてmessageを表示する (eerrorを使う)。メッセージ行の最後には、「[!!]」が付いて、エラーの発生を知らせる。

[hogehoge]は、「hogehogeは省略できる」って意味だ。これらのコマンドを使って、ユーザにメッセージを表示する。

停止

サービスを停止する時のコマンドは、stop()関数の中に書く。

start() {
  ebegin "Stopping Apache"
  apachectl stop
  eend $?
}

基本はstart()と同様。

再起動

再起動は、ちょっと特別に扱わないといけない。

基本的には、stop()start()が自動で実行されるが、特別な処理を行いたい場合がある。その場合は、次のようにして「再起動」であることを判断する。

start() {
  if [ "${RC_CMD}" = "restart" ]; then
    ebegin "Restarting Apache"
    apachectl graceful
  else
    ebegin "Starting Apache"
    apachectl start
  fi

  eend $?
}

stop() {
  if [ "${RC_CMD}" != "restart" ]; then
    ebegin "Stopping Apache"
    apachectl stop
    eend $?
  fi
}

つまり、RC_CMD変数に「指定されたコマンド」が入っているので、それを見るってわけだ。

環境変数

このように、OpenRCのinitスクリプトの中では設定済みの変数がいくつかある。幾つかピックアップ。

RC_SVCNAME このサービスの名前。具体的には、/etc/init.d/hogehogeというinitスクリプトであれば、hogehogeがサービス名になる。
RC_CMD initスクリプトを起動する際に指定されたコマンド。例えば、startstoprestartなど。
RC_UNAME uname -sと同じ。Linuxなら、Linuxが入る。

 

以上、initスクリプト基本編でした。

次回に続く。

*1:もちろん、GentooにはちゃんとApacheのパッケージがあるので、普通はそちらを使う。そちらはこんなに雑じゃない。