起動プロセスをより深く知るためには、シャットダウンプロセスの理解が必要不可欠です。Linux を終了する場合、単に電源を切ることは許されません。単に電源を切ると、深刻な問題をシステムに与えます。
正しいシャットダウンは shutdown プログラムによって行われます。shutdown プログラムの主な役割は シャットダウンをユーザに通知することと、init プログラムにランレベルの変更を依頼することです。
以下のコマンドを実行した場合について説明します。
bash# shutdown -h now |
オプション -h は、シャットダウン後にシステムを停止することを指示します。now は、直ちにシャットダウン処理を行うことを指示します。
まず、shutdown プログラムは、ログインしているユーザにシャットダウンを通知します。そして、init プログラムにランレベルを 0 へ変更するように依頼します。ランレベル 0 は電源遮断状態を表します。
依頼を受けた init プログラムは、すべてのプロセスに SIGTERM、SIGKILL の順でシグナルを送ります。これにより、すべてのプロセスは終了します。そして、/etc/inittab に基づき /etc/rc.d/rc.0 を実行します。
# Set the path. PATH=/sbin:/etc:/bin:/usr/bin |
コマンドを検索するパスを設定します。
# If there are SystemV init scripts for this runlevel, run them. if [ -x /etc/rc.d/rc.sysvinit ]; then . /etc/rc.d/rc.sysvinit fi |
/etc/rc.d/rc.sysvinit が実行可能であれば、/etc/rc.d/rc.sysvinit を実行します。
# Set linefeed mode to avoid staircase effect. stty onlcr |
stty onlcr を実行します。これは、表示が階段状になるのを防ぐための端末設定です。
# Find out how we were called. case "$0" in *0) command="halt" ;; *6) command=reboot ;; *) echo "$0: call me as ¥"rc.0¥" or ¥"rc.6¥" please!" exit 1 ;; esac |
/etc/rc.d/rc.0 は /etc/rc.d/rc.6 へのシンボリックリンクです。すなわち、rc.0 として実行される場合と、rc.6 として実行される場合があります。ここではそれを判別し、rc.0 として実行された場合は、シェル変数 command を "halt" と設定します。rc.6 として実行された場合は、シェル変数 command を reboot と設定します。それら以外の場合は、実行を中止します。
# Save the system time to the hardware clock using hwclock --systohc. # Detect SGI Visual Workstation, since hwclock will make those freeze up: if fgrep -l Cobalt-APIC /proc/interrupts 1> /dev/null 2> /dev/null ; then echo "SGI Visual Workstation detected. Not running hwclock." elif [ -x /sbin/hwclock ]; then if grep "^UTC" /etc/hardwareclock 1> /dev/null 2> /dev/null ; then echo "Saving system time to the hardware clock (UTC)." /sbin/hwclock --utc --systohc else echo "Saving system time to the hardware clock (localtime)." /sbin/hwclock --localtime --systohc fi fi |
ハードウェア時計を設定します。但し、SGI Visual Workstation であることを検出した場合は、何もしません。/sbin/hwclock が実行可能であれば、/etc/hardwareclock を検査します。UTC と記載されている場合は、/sbin/hwclock --utc --systohc を実行します。UTC と記載されていなければ、/sbin/hwclock --localtime --systohc を実行します。
# Stop the Samba server: if [ -x /etc/rc.d/rc.samba ]; then . /etc/rc.d/rc.samba stop fi |
/etc/rc.d/rc.samba が実行可能であれば、/etc/rc.d/rc.samba stop を実行します。これは、Samba を終了します。
# Shut down the NFS server: if [ -x /etc/rc.d/rc.nfsd ]; then /etc/rc.d/rc.nfsd stop fi |
/etc/rc.d/rc.nfsd が実行可能であれば、/etc/rc.d/rc.nfsd stop を実行します。これは、NFS サーバを終了します。
# Unmount any NFS or SMB filesystems: echo "Unmounting remote filesystems." umount -a -r -t nfs,smbfs |
umount -a -r -t nfs,smbfs を実行します。これは、NFS と SMB ファイルシステムをアンマウントします。アンマウントに失敗した場合は、読み取り専用で再マウントします。
# Shut down PCMCIA devices: if [ -x /etc/rc.d/rc.pcmcia ] ; then . /etc/rc.d/rc.pcmcia stop # The cards might need a little extra time here to initialize. sleep 5 fi |
/etc/rc.d/rc.pcmcia が実行可能であれば、/etc/rc.d/rc.pcmcia stop を実行します。これは、PCMCIA デバイスを終了します。また、初期化に時間がかかるため 5 秒待ちます。
# Kill all processes. # INIT is supposed to handle this entirely now, but this didn't always # work correctly without this second pass at killing off the processes. # Since INIT already notified the user that processes were being killed, # we'll avoid echoing this info this time around. if [ "$1" != "fast" ]; then # shutdown did not already kill all processes killall5 -15 sleep 5 killall5 -9 fi |
すべてのプロセスに、SIGTERM、SIGKILL の順でシグナルを送ります。これは、すでに init プログラムによって行われていますが、念のためにもう一度ここで行います。
# Try to turn off quota: if fgrep quota /etc/fstab 1> /dev/null 2> /dev/null ; then if [ -x /sbin/quotaoff ]; then echo "Turning off filesystem quotas." /sbin/quotaoff -a fi fi |
/etc/fstab を読み込み、Quota が使われていることを検出した場合、/sbin/quotaoff を調べます。/sbin/quotaoff が実行可能であれば、/sbin/quotaoff -a を実行します。
# Before unmounting file systems write a reboot or halt record to wtmp. $command -w |
$command -w を実行します。これは、ファイルシステムをアンマウントする前に wtmp を更新するために実行します。
# Carry a random seed between reboots. # Save 512 bytes, which is the size of the entropy pool. echo "Saving random seed from /dev/urandom in /etc/random-seed." dd if=/dev/urandom of=/etc/random-seed count=1 bs=512 2> /dev/null |
dd if=/dev/urandom of=/etc/random-seed count=1 bs=512 2> /dev/null を実行します。これは、より良い乱数を発生させるための仕組みです。
# Clear /var/lock/subsys. if [ -d /var/lock/subsys ]; then rm -f /var/lock/subsys/* fi |
/var/lock/subsys がディレクトリであれば、rm -f /var/lock/subsys/* を実行します。これは、/var/lock/subsys/ 内のファイルをすべて削除します。
# Turn off swap, then unmount local file systems. echo "Turning off swap." swapoff -a echo "Unmounting local file systems." # Don't remount UMSDOS root volumes: if [ ! "`mount | head -1 | cut -d ' ' -f 5`" = "umsdos" ]; then umount -a -r -t nonfs echo "Remounting root filesystem read-only." mount -n -o remount,ro / else umount -a -r -t nonfs,noumsdos,nosmbfs fi |
スワッピングを無効にします。次に、ルートファイルシステムを調べます。ファイルシステムが UMSDOS であれば、ルートファイルシステム以外をアンマウントします。ファイルシステムが UMSDOS でない場合は、すべてのファイルシステムをアンマウントし、ルートファイルシステムを読み取り専用で再マウントします。
# This never hurts: sync |
sync を実行します。
# If we're using LVM, we need to deactivate the volume groups: if [ -r /etc/lvmtab ]; then /sbin/vgchange -an fi |
/etc/lvmtab が読み込み可能であれば、/sbin/vgchange -an を実行します。
# sleep 1 fixes problems with some hard drives that don't # otherwise finish syncing before reboot or poweroff sleep 1 |
1 秒待ちます。
# This is to ensure all processes have completed on SMP machines: wait |
すべてのプロセスの終了を待ちます。
if [ -x /sbin/genpowerd ]; then # See if this is a powerfail situation: if grep FAIL /etc/upsstatus 1> /dev/null 2> /dev/null ; then # Signal UPS to shut off the inverter: /sbin/genpowerd -k /dev/ttyS4 tripp-nt if [ ! $? = 0 ]; then echo echo "There was an error signaling the UPS." echo "Perhaps you need to edit /etc/rc.d/rc.6 to configure" echo "the serial line and UPS type." # Wasting 15 seconds of precious power: sleep 15 fi fi fi |
/sbin/genpowerd が実行可能であれば、/etc/upsstatus を読み込み rc.0 の実行が、電源異常によるものであるかを確認します。電源異常によるものであれば、/sbin/genpowerd -k /dev/ttyS4 tripp-nt を実行し UPS に電源遮断を依頼します。UPS への依頼においてエラーが生じた場合はメッセージを表示します。
# Now halt (poweroff with APM kernels) or reboot. if [ "$command" = "reboot" ]; then echo "Rebooting." reboot else poweroff fi |
$command が reboot であれば、reboot を実行します。それ以外であれば、poweroff を実行します。
実際には、reboot と poweroff は halt へのシンボリックリンクです。halt は reboot として実行された場合と、poweroff として実行された場合に応じて動作を変えます。
poweroff として実行された halt は、オプション -p が指定されたものとして動作します。すなわち、システム停止後に電源を遮断します。但し、電源遮断には APM サポートが必要です。
最後に、以下のコマンドを実行した場合について説明します。
bash# shutdown -r now |
オプション -r は、シャットダウン後にシステムを再起動することを指示します。
オプション -h との違いは、init プログラムに依頼するランレベルのみです。オプション -h を付けた場合は、ランレベル 6 へ変更するように依頼します。ランレベル 6 は再起動状態を表します。
依頼を受けた init プログラムは /etc/inittab に基づき /etc/rc.d/rc.6 を実行します。
そして、最後に reboot を実行します。
参考文献
前へ | 起動プロセス入門 | 次へ |