自動起動スクリプト(rc)

PostgreSQL自動起動スクリプト(rc)が欲しい。というわけで先日インストールしたソースの配下を漁ってみる。
…がいくら漁ってみても見つからない。で、googlingしてみたら皆さん自作しているようだ。でもgoogleで引っかかったものは正直なところ『う〜ん…』といった内容のもの。いやそんなに見てないけどさ。最低限の事はやってるけどあとちょっと足りないという感じ。そこでピンッと思いついた。RPMでもそもそもあるんだから自動起動スクリプトだって用意されているはずだよね。だったらそこから引っこ抜いてくれば良いじゃん!って。というわけで自動起動スクリプト(rc)を引っこ抜いてみる事にする。

RPMパッケージからファイルを取り出す
http://d.hatena.ne.jp/sin-j/20080812/1218527559

取り出してはみたものの、ふと思う。これって勝手に編集して使い回しても良いのかしら?んー…きっと大丈夫だよね。というわけで取り出したファイルを元に大幅に編集して検証環境用の自動起動スクリプトを作成する。

スクリプト

#!/bin/sh
# postgresql    This is the init script for starting up the PostgreSQL
#               server
#
# chkconfig: - 64 36
# description: Starts and stops the PostgreSQL backend daemon that handles \
#              all database requests.
# processname: postmaster
# pidfile: /var/run/postmaster.pid

# PGVERSION is the full package version, e.g., 7.4.7
PGVERSION=8.3.3
# PGMAJORVERSION is major version, e.g., 7.4 (this should match PG_VERSION)
PGMAJORVERSION=`echo "$PGVERSION" | sed 's/^\([0-9]*\.[0-9]*\).*$/\1/'`

# Source function library.
. /etc/rc.d/init.d/functions

# Get function listing for cross-distribution logic.
TYPESET=`typeset -f|grep "declare"`

# Get config.
. /etc/sysconfig/network

# Find the name of the script
NAME=`basename $0`
if [ ${NAME:0:1} = "S" -o ${NAME:0:1} = "K" ]
then
        NAME=${NAME:3}
fi

# For SELinux we need to use 'runuser' not 'su'
if [ -x /sbin/runuser ]
then
    SU=runuser
else
    SU=su
fi


# Set defaults for configuration variables
PGENGINE=/usr/local/postgresql-8.3.3/bin
PGPORT=5432
PGDATA=/opt/postgresql-8.3.3
PGLOG=/opt/postgresql-8.3.3/pgstartup.log

# Override defaults from /etc/sysconfig/pgsql if file is present
[ -f /etc/sysconfig/pgsql/${NAME} ] && . /etc/sysconfig/pgsql/${NAME}

export PGDATA
export PGPORT

# Check that networking is up.
# Pretty much need it for postmaster.
[ "${NETWORKING}" = "no" ] && exit 1

[ -f "$PGENGINE/postmaster" ] || exit 1

script_result=0

start(){
        PSQL_START=$"Starting ${NAME} service: "

        # Make sure startup-time log file is valid
        if [ ! -e "$PGLOG" -a ! -h "$PGLOG" ]
        then
                touch "$PGLOG" || exit 1
                chown postgres:postgres "$PGLOG"
                chmod go-rwx "$PGLOG"
                [ -x /usr/bin/chcon ] && /usr/bin/chcon -u system_u -r object_r -t postgresql_log_t "$PGLOG" 2>/dev/null
        fi

        # Check for the PGDATA structure
        if [ -f "$PGDATA/PG_VERSION" ] && [ -d "$PGDATA/base" ]
        then
        # Check version of existing PGDATA

                if [ x`cat "$PGDATA/PG_VERSION"` != x"$PGMAJORVERSION" ]
                then
                        SYSDOCDIR="(Your System's documentation directory)"
                        if [ -d "/usr/doc/postgresql-$PGVERSION" ]
                        then
                                SYSDOCDIR=/usr/doc
                        fi
                        if [ -d "/usr/share/doc/postgresql-$PGVERSION" ]
                        then
                                SYSDOCDIR=/usr/share/doc
                        fi
                        if [ -d "/usr/doc/packages/postgresql-$PGVERSION" ]
                        then
                                SYSDOCDIR=/usr/doc/packages
                        fi
                        if [ -d "/usr/share/doc/packages/postgresql-$PGVERSION" ]
                        then
                                SYSDOCDIR=/usr/share/doc/packages
                        fi
                        echo
                        echo $"An old version of the database format was found."
                        echo $"You need to upgrade the data format before using PostgreSQL."
                        echo $"See $SYSDOCDIR/postgresql-$PGVERSION/README.rpm-dist for more information."
                        exit 1
                fi

        # No existing PGDATA! Initdb it.

        else
                echo -n $"Initializing database: "
                if [ ! -e "$PGDATA" -a ! -h "$PGDATA" ]
                then
                        mkdir -p "$PGDATA" || exit 1
                        chown postgres:postgres "$PGDATA"
                        chmod go-rwx "$PGDATA"
                fi
                # Clean up SELinux tagging for PGDATA
                [ -x /sbin/restorecon ] && /sbin/restorecon "$PGDATA"
                # Initialize the database
                $SU -l postgres -c "$PGENGINE/initdb --pgdata='$PGDATA' --auth='ident sameuser'" >> "$PGLOG" 2>&1 < /dev/null
                # Create directory for postmaster log
                mkdir "$PGDATA/pg_log"
                chown postgres:postgres "$PGDATA/pg_log"
                chmod go-rwx "$PGDATA/pg_log"

                [ -f "$PGDATA/PG_VERSION" ] && echo_success
                [ ! -f "$PGDATA/PG_VERSION" ] && echo_failure
                echo
        fi

        echo -n "$PSQL_START"
        $SU -l postgres -c "$PGENGINE/postmaster -p '$PGPORT' -D '$PGDATA' ${PGOPTS} &" >> "$PGLOG" 2>&1 < /dev/null
        sleep 2
        pid=`pidof -s "$PGENGINE/postmaster"`
        if [ $pid ] && [ -f "$PGDATA/postmaster.pid" ]
        then
                success "$PSQL_START"
                touch /var/lock/subsys/${NAME}
                head -n 1 "$PGDATA/postmaster.pid" > "/var/run/postmaster.${PGPORT}.pid"
                echo
        else
                failure "$PSQL_START"
                echo
                script_result=1
        fi
}

stop(){
        echo -n $"Stopping ${NAME} service: "
        $SU -l postgres -c "$PGENGINE/pg_ctl stop -D '$PGDATA' -s -m fast" > /dev/null 2>&1 < /dev/null
        ret=$? 
        if [ $ret -eq 0 ]
        then
                echo_success
        else
                echo_failure
                script_result=1
        fi
        echo
        rm -f "/var/run/postmaster.${PGPORT}.pid"
        rm -f "/var/lock/subsys/${NAME}"
}

restart(){
    stop
    start
}

condrestart(){
    [ -e /var/lock/subsys/${NAME} ] && restart
}

condstop(){
    [ -e /var/lock/subsys/${NAME} ] && stop
}

reload(){
    $SU -l postgres -c "$PGENGINE/pg_ctl reload -D '$PGDATA' -s" > /dev/null 2>&1 < /dev/null
}

# This script is slightly unusual in that the name of the daemon (postmaster)
# is not the same as the name of the subsystem (postgresql)

# See how we were called.
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  status)
        status postmaster
        script_result=$?
        ;;
  restart)
        restart
        ;;
  condrestart)
        condrestart
        ;;
  condstop)
        condstop
        ;;
  reload|force-reload)
        reload
        ;;
  *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart|condstop|reload|force-reload}"
        exit 1
esac

exit $script_result

正直なところここまでいらないなぁと思いつつも引っこ抜くのが面倒だったのでこれだけ。元からのやつにほとんど手を入れていませぬ。でも起動・停止ともにできたのでOKでしょ。

自動起動(rc)に登録しておく

[root@CentOS-5.2 ~]# chkconfig --list postgresql
サービス postgresql は chkconfig をサポートしますが実行レベルで参照されていません (run 'chkconfig --add postgresql')
[root@CentOS-5.2 ~]# chkconfig --add postgresql
[root@CentOS-5.2 ~]# chkconfig --list postgresql
postgresql      0:off   1:off   2:off   3:off   4:off   5:off   6:off
[root@CentOS-5.2 ~]# chkconfig  postgresql on
[root@CentOS-5.2 ~]# chkconfig --list postgresql
postgresql      0:off   1:off   2:on    3:on    4:on    5:on    6:off
[root@CentOS-5.2 ~]# 

確認。

[root@CentOS-5.2 ~]# ls -l /etc/rc.d/rc?.d/*postgresql
lrwxrwxrwx 1 root root 20  8月 13 01:41 /etc/rc.d/rc0.d/K36postgresql -> ../init.d/postgresql
lrwxrwxrwx 1 root root 20  8月 13 01:41 /etc/rc.d/rc1.d/K36postgresql -> ../init.d/postgresql
lrwxrwxrwx 1 root root 20  8月 13 01:41 /etc/rc.d/rc2.d/S64postgresql -> ../init.d/postgresql
lrwxrwxrwx 1 root root 20  8月 13 01:41 /etc/rc.d/rc3.d/S64postgresql -> ../init.d/postgresql
lrwxrwxrwx 1 root root 20  8月 13 01:41 /etc/rc.d/rc4.d/S64postgresql -> ../init.d/postgresql
lrwxrwxrwx 1 root root 20  8月 13 01:41 /etc/rc.d/rc5.d/S64postgresql -> ../init.d/postgresql
lrwxrwxrwx 1 root root 20  8月 13 01:41 /etc/rc.d/rc6.d/K36postgresql -> ../init.d/postgresql
[root@CentOS-5.2 ~]# 

ちなみに…このK○○とS○○は、

  • K:kill - 停止
  • S:start - 起動

であり、番号は起動もしくは停止していく順番である。小さい番号から起動・停止を行っていく。この番号とrunlevelについてはそのうち。

追記

コメントを頂いたので追記。
ソースを展開したディレクトリ配下

contrib/start-scripts

[postgres@CentOS-5.2 start-scripts]$ find /usr/local/src/postgresql-8.3.3/contrib/start-scripts/ -type f
/usr/local/src/postgresql-8.3.3/contrib/start-scripts/freebsd
/usr/local/src/postgresql-8.3.3/contrib/start-scripts/linux
/usr/local/src/postgresql-8.3.3/contrib/start-scripts/osx/install.sh
/usr/local/src/postgresql-8.3.3/contrib/start-scripts/osx/PostgreSQL
/usr/local/src/postgresql-8.3.3/contrib/start-scripts/osx/README
/usr/local/src/postgresql-8.3.3/contrib/start-scripts/osx/StartupParameters.plist
[postgres@CentOS-5.2 start-scripts]$ 

ほほぅ。freebsd, linux, osx用のモノが既に用意されているとのこと。linuxファイルを確認すると…こっちの方がすっきりしてる!RPMのパッケージから拾ってきた方は最初の起動等を考えられているのか(?)ディレクトリが無かったら作ったりなんかいろいろなチェックが入っているけど、starts-scripts/linuxの方はとってもスッキリ。検証サーバもスクリプトを置き換えだ!prefix, PGDATAのパスを書き換えて、serviceコマンドで動作確認。

> ishikawa84g 様
ありがとうございました。とーってもお勉強になりました。