Linux

Linuxでシャットダウン時に想定した処理が実行されない

More than 3 years have passed since last update.

シャットダウン時にhogeというスクリプトを実行したくて

  • /etc/init.d/hoge
  • /etc/rc0.d/K99hoge
  • /etc/rc1.d/K99hoge
  • /etc/rc6.d/K99hoge

と配置したのに実行されてなかったので調査した時のメモ

結論

/var/lock/subdys/配下に

  • hoge
  • hoge.init

がなかったので。

参考

そもそも/etc/rc0.d/とかって何か?

/etc/rc0.d/とかの数字の部分はランレベルを示します。
それぞれのランレベルは以下のとおり。

ランレベル 概要
0 システムの停止
1 シングルユーザーモード
2 マルチユーザーモード(NFSなし)
3 マルチユーザーモード(テキストログイン)
4 未使用
5 マルチユーザーモード(グラフィカルログイン)
6 システムの再起動

上記より、終了したいスクリプトはランレベル0とランレベル6の時に実行されるように設定がきればOKです。あとランレベル1の時のシングルユーザーモードでは必要最小限のサービスだけにする必要があるので、マルチユーザーモードで動いているサービスを明示的に止めるため場合にはランレベル1の時に明示的に停止させるように設定する必要があります。

スクリプトの前のKとかSって何か?

/etc/rc.d/rc
#! /bin/bash
#
# rc            This file is responsible for starting/stopping
#               services when the runlevel changes.
#
# Original Author:
#               Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
#
... 

# First, run the KILL scripts.
for i in /etc/rc$runlevel.d/K* ; do

        # Check if the subsystem is already up.
        subsys=${i#/etc/rc$runlevel.d/K??}
        [ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] || continue
        check_runlevel "$i" || continue

        # Bring the subsystem down.
        [ -n "$UPSTART" ] && initctl emit --quiet stopping JOB=$subsys
        $i stop
        [ -n "$UPSTART" ] && initctl emit --quiet stopped JOB=$subsys
done

# Now run the START scripts.
for i in /etc/rc$runlevel.d/S* ; do

        # Check if the subsystem is already up.
        subsys=${i#/etc/rc$runlevel.d/S??}
        [ -f /var/lock/subsys/$subsys ] && continue
        [ -f /var/lock/subsys/$subsys.init ] && continue
        check_runlevel "$i" || continue

        # If we're in confirmation mode, get user confirmation
        if [ "$do_confirm" = "yes" ]; then
                confirm $subsys
                rc=$?
                if [ "$rc" = "1" ]; then
                        continue
                elif [ "$rc" = "2" ]; then
                        do_confirm="no"
                fi
        fi

        update_boot_stage "$subsys"
        # Bring the subsystem up.
        [ -n "$UPSTART" ] && initctl emit --quiet starting JOB=$subsys
        if [ "$subsys" = "halt" -o "$subsys" = "reboot" ]; then
                export LC_ALL=C
                exec $i start
        fi
        $i start
        [ -n "$UPSTART" ] && initctl emit --quiet started JOB=$subsys
done
[ "$do_confirm" = "yes" ] && rm -f /var/run/confirm
exit 0

ということでランレベルが変わる時に

  • /etc/rcランレベル/K数字となっているスクリプトが数字が若い順に第一引数stopで実行される
  • 次に/etc/rcランレベル/K数字となっているスクリプトが数字が若い順に第一引数startで実行される

ということが分かります。なので、例えばランレベル3とかにK01hogeとS01fugaというスクリプトを置くことも出来て、その場合、K01hogeの方が先に実行される

/var/lock/subdys/?

上記スクリプトの中で[ -f /var/lock/subsys/$subsys -o -f /var/lock/subsys/$subsys.init ] || continueという部分があり、ファイルがないとそもそもKスクリプトは実行されないことになっています

なので終了したいスクリプトの引数がstartで呼び出された時にはtouchコマンドを作って/var/lock/subdys/hoge/var/lock/subdys/hoge.initというファイルを作成する必要があります

hoge
!/bin/sh

lock_file="/var/lock/subsys/hoge"

start()
{
    touch ${lock_file}

    # 何か

}

stop()
{
    rm -r ${lock_file}

    # 何か
}

case "$1" in
    start)
        start
    ;;
    stop)
        stop
    ;;
    *)
        echo "Usage: $0 {start|stop}"
    ;;
esac

exit 0