Posted at

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