SysVinit

提供: ArchWiki
ナビゲーションに移動 検索に移動

関連記事

警告: SysVinit は Arch Linux ではもはや用いられなくなり公式リポジトリから落とされました [1]systemd に移行することを推奨します。

SysVinit を使用するシステムでは、Linux カーネルがロードされたあと init が一番最初のプロセスとして起動します。カーネルによって使われるデフォルトの init プログラムは /sbin/init であり systemd-sysvcompat (新しい環境でのデフォルト、systemd) や sysvinitAUR に含まれています。この記事において init という言葉は sysvinit のことを指します。

inittab/etc に置かれた init の起動設定ファイルのことです。特定のランレベルに入ったときにどのプログラムやスクリプトを実行すればいいのか init に指定します。

SysVinit ベースでありながら Arch のシステムでは init は使用せず、ほとんどの作業は実際にはメインのブートスクリプトが担っています。この記事では init と inittab について取り上げます。

インストール

AUR から sysvinitAURinitscripts-forkAUR パッケージをインストールしてください。インストールすると systemd-sysvcompat が削除され、再起動後に sysvinit が使われるようになります。systemd に戻したい場合、カーネルコマンドラインinit=/usr/lib/systemd/systemd を追加してください。

init スクリプトの代わりとなるスクリプトが arch-rcscripts に存在します。設定方法については Init#設定を参照してください。

init と inittab の概要

init はいつでもプロセス1であり、スワップ領域の管理を除いて、全ての他のプロセスの親プロセスになります。pstree を使うことでシステムのプロセス階層のどこに init があるか知ることができます:

$ pstree -Ap
init(1)-+-acpid(3432)
        |-crond(3423)
        |-dbus-daemon(3469)
        |-gpm(3485)
        |-mylogin(3536)
        |-ngetty(3535)---login(3954)---zsh(4043)---pstree(4326)
        |-polkitd(4033)---{polkitd}(4035)
        |-syslog-ng(3413)---syslog-ng(3414)
        `-udevd(643)-+-udevd(3194)
                     `-udevd(3218)

(名前の通り) システムの初期化をする他に、init は再起動やシャットダウン、リカバリモード (シングルユーザーモード) での起動も管理します。これらに対応するために、inittab はエントリを異なるランレベルにグループ化しています。Arch が使用するランレベルはそれぞれ、halt には 0、シングルユーザーモードには 1 (エイリアスで S)、通常の起動時 (マルチユーザーモード) には 3、X には 5、再起動には 6 です。別のディストロではランレベルが異なっている可能性がありますが 0, 1, 6 については全てのディストロで共通です。

起動時に、init は inittab を見て適切なアクションを実行します。inittab のエントリは以下のような形式を取ります:

id:runlevels:action:process

id はエントリのユニークな識別子 (ただの名前で、init に影響は与えません) で、runlevels はランレベルの文字 (区切りなし) です。init のランレベルが runlevels になると、action が実行され、適当なときに process が実行されます。特殊な action を指定すると init は runlevels を無視して特殊なマッチング方法を使います。詳しい説明は次のセクションにあります。

man 5 inittabman 8 init も参照してください。

ランレベルの切り替え

ブートローダー

システムが起動するときのランレベルを変更するには、ブートローダーの適当な設定行に起動したいランレベル n を追加します。一度だけ別のランレベルで起動したいときは、ランレベルの数字をカーネルパラメータに追加してください (例: ランレベル 3 の場合 3)。

ランレベルは一番最後に付けることでカーネルが起動するべきランレベルを知ることができます。別の init プログラムを使うには (例: systemd)、init=/usr/lib/systemd/systemd などを追加します。

ノート: sysvinit 以外の init を使用する場合、ランレベルのパラメータは無視されることがあります。

起動後

システムが起動した後は、telinit n を実行することで init にランレベルを n に変更するように要求できます。init は inittab を読み込んでランレベル n と現在のランレベルを比較して、新しいランレベルには存在しないプロセスを終了して、古いランレベルに存在しないアクションを実行します。両方のランレベルに存在するプロセスはそのままで手をつけられません。実際には、終了の方法はもう少し複雑です。技術的な詳細は init の man ページにあります。

init は inittab を監視しません。inittab に変更を加えて、その変更を適用するには telinit を明示的に呼び出す必要があります。telinit q コマンドは init に inittab を再調査させますがランレベルは変更しません。

inittab

このセクションでは inittab の一般的なエントリについて考察します。Arch で使用されるデフォルトの inittab のエントリと同じ順番で説明します。その後、各自で inittab エントリを作成するのに役立つ例をあげます。

警告: /etc/inittab に修正を加えたら再起動する前に telinit q でテストしてください。ちっぽけな構文エラーでシステムが起動しなくなることがあります。

デフォルトのランレベル

デフォルトのランレベルは 3 です。デフォルトで (X で使用することになっている) ランレベル 5 で起動したい場合は以下をアンコメントまたは追加してください:

id:5:initdefault:

メインのブートスクリプト

以下がメインの Arch init スクリプトです。

rc::sysinit:/etc/rc.sysinit
rs:S1:wait:/etc/rc.single
rm:2345:wait:/etc/rc.multi
rh:06:wait:/etc/rc.shutdown

シングルユーザーブート

キーファイルが見つからなかったり、ハードドライブやファイルシステムが破損したり死亡するなどして、カーネルが途中で起動しなくなることがあります。そのような場合、init イメージは自動的にシングルユーザーモードに移行して root ログインができるようになり、/sbin/login の代わりに /sbin/sulogin を使ってログインプロセスを制御します。GRUB, LILO, Syslinux などの設定のカーネルコマンドラインに S という文字を追加することでもシングルユーザーモードで起動できます。sulogin 以外を実行させたい場合は、以下の部分に記述してください。

su:S:wait:/sbin/sulogin -p

Getty とログイン

以下はターミナルで getty を実行する重要なエントリです。デフォルト設定では複数の getty が tty1-6 で動作するようになっており、ログインプロンプトで画面に表示されます。openvt, chvt, stty, ioctl なども参照してください。

c1:234:respawn:/sbin/agetty 9600 tty1 xterm-color
c5:5:respawn:/sbin/agetty 57600 tty2 xterm-256color

Ctrl+Alt+Del

特殊なキーシーケンス Ctrl+Alt+Del が押されると、以下が実行されます。

ca::ctrlaltdel:/sbin/shutdown -t3 -r now

X プログラム

デバッグを厭わない場合は、inittab からあらゆる種類のプログラムを起動する方法を見つけ出すことができます。有用なプログラムのタイプとしてはランレベルが 5 で、multi-user-x-mode のときにログインマネージャを起動することが挙げられます。以下の例ではランレベルが 5 になったときに SLiM を起動する方法がわかります。

x:5:respawn:/usr/bin/slim >/dev/null 2>&1
#x:5:respawn:/usr/bin/xdm -nodaemon -confi /etc/X11/xdm/archlinux/xdm-config

電源検出スクリプト

Init は UPS デバイスを照会して UPS の状態にあわせてプロセスを実行することができます。例えば:

pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"
pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"

カスタムキーボードリクエスト

以下の行は特別なキーシーケンスが押された時のカスタム関数を追加します。Ctrl+Alt+Del と同じようにこの特別なキーシーケンスは自由に修正することができます。

kb::kbrequest:/usr/bin/wall "Keyboard Request -- edit /etc/inittab to customize"

kbrequest のトリガー

init プロセス (1) に root で (sudo を使って) WINCH シグナルを送信することで特殊なキーシーケンス kbrequest を起こすことができます。以下の例では、次のコマンドによって wall が全ての tty に書き込みを行います:

kill -WINCH 1
Broadcast message from root@askapachehost (console) (Wed Oct 27 14:02:26 2010):
Keyboard Request -- edit /etc/inittab to customize

rc.d スクリプトの書き方

Initscripts は rc.d スクリプトを使用してデーモンの起動・停止・再起動を制御します。

ガイドライン

  • /etc/rc.conf, /etc/rc.d/functions, /etc/conf.d/DAEMON_NAME を参照してください。
  • 引数などデーモンオプションは /etc/conf.d/DAEMON_NAME に記述します。ロジックから設定を分離してデーモンスクリプトの形式を乱さないための決まり事です。
  • 無駄な機能を書くのを避けて /etc/rc.d/functions の関数を利用してください。
  • 最低でもスクリプトの引数として start, stop, restart を定義してください。

利用可能な関数

  • /etc/rc.d/functions によって様々な関数が提供されています:
    • stat_busy "message": メッセージで busy 状態を設定 (例: Starting daemon [BUSY])
    • stat_done: done 状態を設定 (例: Starting daemon [DONE])
    • stat_fail: failed 状態を設定 (例: Starting daemon [FAILED])
    • get_pid program: プログラムの PID を取得
    • ck_pidfile PID-file program: プログラムの PID ファイルが正しいかどうかチェック (例: ck_pidfile /var/run/daemon.pid daemon || rm -f /var/run/daemon.pid)
    • [add|rm]_daemon program: (/run/daemons/ に存在する) 実行中のデーモンにプログラムを追加・削除

関数の完全なリストは長すぎてドキュメント化もされていないため /etc/rc.d/functions のソースから学ぶしかありません。man rc.d も参照してください。

サンプル

以下は crond の例です。/etc/rc.d には様々な亜種が存在します。

設定ファイル:

/etc/conf.d/crond
ARGS="-S -l info"

実際のスクリプト:

/etc/rc.d/crond
#!/bin/bash

. /etc/rc.conf
. /etc/rc.d/functions

DAEMON=crond
ARGS=

[ -r /etc/conf.d/$DAEMON ] && . /etc/conf.d/$DAEMON

PID=$(get_pid $DAEMON)

case "$1" in
 start)
   stat_busy "Starting $DAEMON"
   [ -z "$PID" ] && $DAEMON $ARGS &>/dev/null
   if [ $? = 0 ]; then
     add_daemon $DAEMON
     stat_done
   else
     stat_fail
     exit 1
   fi
   ;;
 stop)
   stat_busy "Stopping $DAEMON"
   [ -n "$PID" ] && kill $PID &>/dev/null
   if [ $? = 0 ]; then
     rm_daemon $DAEMON
     stat_done
   else
     stat_fail
     exit 1
   fi
   ;;
 restart)
   $0 stop
   sleep 1
   $0 start
   ;;
 *)
   echo "usage: $0 {start|stop|restart}"  
esac

systemd への移行

移行前に考慮すべきこと

  • インタラクティブな initscriptssystemd では動作しません。

追加情報

  • systemd を使用している場合、ユーザーのグループ (sys, disk, lp, network, video, audio, optical, storage, scanner, power など) を設定する必要はほとんどありません。グループは機能を破壊することさえあります。例えば audio グループは高速なユーザー切り替えやアプリケーションのソフトウェアミキシングを無効にします。全ての PAM ログインは logind セッションを提供します。オーディオ/ビデオデバイスに POSIX ACL を通して権限を与えたり、udisks を使ってリムーバブルディスクのマウントなどの操作を行います。

参照