LoginSignup
29

More than 5 years have passed since last update.

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

Posted at

シャットダウン時に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

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29