6 ブート方法が変わるよ

まえだこうへ い

PIC
____________________________________________________________________

6.1 Squeeze からブート方法が変わる

Debian のブートの仕組みには、 System-V 系 Unix では伝統的な init (sysvinit) が使われています。 Debian の次期安定版 6.0 (コードネーム Squeeze) から、 これが upstart に変わる予定です。 今年の 3 月にフリーズ予定、 8 月にリリース予定の Squeeze での予習の意味を込めて、 今回はこの upstart に変わることになった背景、 init との比較を含めた upstart の仕組み、 実際に切り替え方法について説明します。

6.1.1 背景

upstart は、 Debian をベースとしたディストリビューションである、 Ubuntu 独自に sysvinit の後継の仕組み として開発されました。 元々 sysvinit は伝統的で安定した仕組みではありますが、 現在使われているハー ドウェアで使うには機能面、 性能面から問題が出てきています。 そこで、 sysvinit の後継の仕組みとして、 upstart 以外にも複数のブートプロセスの仕組みが開発されています。 しかし、 Ubuntu 以外にも Fedora 、 また Google の Chrome OS, Chromium OS でも upstart が採用されています。 Debian でも Squeeze か ら採用される予定ということもあり、 sysvinit の後継は upstart に落ち着く可能性が高いのではないでしょ うか。

6.1.2 そもそも init って何よ?

upstart の話をする前に、 init って何?という人向けにまず説明しましょう。 init は今更説明しなくても知っとるがな、 という 読者は、 先に読み進めてください。

init は Unix/Linux システムにおいて、 カーネルがブートした後、 ユーザプログラムが起動するための仕組みです。 例 えば、 あなたの使っているノート PC やサーバに入っている Debian システムでもこの仕組みが必ず入っ ています。 マシンに電源を入れてから、 ログイン画面が表示されるまでの流れは大まかには次のようになり ま す 。



図 2: ブートの流れ

PIC


init プロセスが起動すると、 init は /etc/inittab の内容に従って、 プロセスのを生成や停止を行います。 inittab の書式は次 のようになります。

id:runlevels:action:process

プロセスの生成に関わる部分には以下のようなものがあります。

si::sysinit:/etc/init.d/rcS

l1:1:wait:/etc/init.d/rc 1
l2:2:wait:/etc/init.d/rc 2
l3:3:wait:/etc/init.d/rc 3
l4:4:wait:/etc/init.d/rc 4
l5:5:wait:/etc/init.d/rc 5

一行目にランレベルの指定が無いのは、 action に sysinit が指定されているためです。 これはステムブート中に実行され、 他 のブート用の action よりも優先して実行されます。 /etc/init.d/rcS では

exec /etc/init.d/rc S

だけが実行されます。 これは /etc/init.d/rc でのブート用の変数を設定します。 この後、 上記の rc スクリプトに対し、 起動 時に指定するランレベルを引数として実行されますが、 Debian でのデフォルトは、 ランレベル 2 で起動され ます。

id:2:initdefault:

なので、 実際には下記が実行されます。

l2:2:wait:/etc/init.d/rc 2

これにより /etc/rc2.d 以下のファイル名が SNN で始まるスクリプトが NN の二桁の数字の部分が” 昇順となるように一 つずつ実行” されます。 これが起動が遅くなる原因の一つにもなっています。 ただし、 同じレベルのスクリプトは並行して実行 されるようにはなっています。

# Now run the START scripts for this runlevel.
# Run all scripts with the same level in parallel
CURLEVEL=""
for s in /etc/rc$runlevel.d/S*
do
        # Extract order value from symlink
        level=${s#/etc/rc$runlevel.d/S}
        level=${level%%[a-zA-Z]*}
        if [ "$level" = "$CURLEVEL" ]
        then
                continue
        fi
        CURLEVEL=$level
        SCRIPTS=""
        for i in /etc/rc$runlevel.d/S$level*
        do
                [ ! -f $i ] && continue

                suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9]}
                if [ "$previous" != N ]
                then
                        #
                        # Find start script in previous runlevel and
                        # stop script in this runlevel.
                        #
                        stop=/etc/rc$runlevel.d/K[0-9][0-9]$suffix
                        previous_start=/etc/rc$previous.d/S[0-9][0-9]$suffix
                        #
                        # If there is a start script in the previous level
                        # and _no_ stop script in this level, we don’t
                        # have to re-start the service.
                        #
                        if [ start = "$ACTION" ] ; then
                                [ -f $previous_start ] && [ ! -f $stop ] && continue
                        else
                                # Workaround for the special
                                # handling of runlevels 0 and 6.
                                previous_stop=/etc/rc$previous.d/K[0-9][0-9]$suffix
                                #
                                # If there is a stop script in the previous level
                                # and _no_ start script there, we don’t
                                # have to re-stop the service.
                                #
                                [ -f $previous_stop ] && [ ! -f $previous_start ] && continue
                        fi

                fi
                SCRIPTS="$SCRIPTS $i"
                if is_splash_stop_scripts "$suffix" ; then
                        $debug splash_stop || true
                fi
        done
        startup $ACTION $SCRIPTS
done

起動スクリプトの起動以外には、 ランレベル 2 から 5 または、 2 か 3 の時にはコンソールから getty が実行されます。 action が respawn となっていますが、 これは getty プログラムが終了したら、 init が再起動させるための指示です。 あるユー ザがコンソールからログインしたセッションを、 ログアウトすると getty は終了しますが、 init により再びログイン画面で待 ち受けることができる、 というわけです。

1:2345:respawn:/sbin/getty 38400 tty1
2:23:respawn:/sbin/getty 38400 tty2
3:23:respawn:/sbin/getty 38400 tty3
4:23:respawn:/sbin/getty 38400 tty4
5:23:respawn:/sbin/getty 38400 tty5
6:23:respawn:/sbin/getty 38400 tty6

init の他の役割としては、 システム停止時のプロセスの停止にも関わっています。

6.2 upstart とは

それでは、 init についての予備知識を得たところで、 本題の upstart に入りましょう。 README にも記述されている upstart の主な特徴は次の 6 つです。

sysvinit とは異なり、 イベントドリブンで非同期にタスクやサービスが起動される点が一番大きな違いでしょう。 ただし、 現 在、 Squeeze/Sid で採用されている upstart は、 sysvinit の互換モードのものです。 upstart の最終目標は、 イベントドリ ブンのブートプロセスに完全に移行することですが、 互換モードでは、 sysvinit の動作を模倣しています。 *12

ma upstart の状態遷移は次の図のようになります。 *13



図 3: upstart 状態遷移

PIC


6.2.1 sysvinit と変わらない点

Debian の upstart は、 前述のとおり、 Debian システムの起動・停止という重要な部分の置き換えを行う ため互換モードのものが採用されています、 下記は sysvinit と仕様上の変更がない部分です。 なお、 この 6.2.1と次の 6.2.2は upstart パッケージの README.Debian.gz に記載されている FAQ をまとめ直したもの です。

6.2.2 sysvinit と違う点

互換モードでも全てが sysvinit と動作が同じというわけではなく、 upstart の固有の部分もあります。 主に getty 関連の設定 が変わる点が大きな違いです。

6.3 upstart への切り替え

それでは、 早速 sysvinit から upstart へ切り替えてみましょう。 Squeeze/Sid と Lenny との場合を見てみ ます。

6.3.1 Squeeze/Sid での場合

Squeeze/Sid での upstart への切り替えには、 upstart パッケージをインストールします。 通常のパッケージのインストールと は異なり、 続行する場合は、 Yes, do as I say と入力しなさい、 というメッセージが表示されます。 これは入れ替えは非常に リスクが高いためです。

$ sudo apt-get install upstart
パッケージリストを読み込んでいます...  完了
依 存 関 係 ツ リ ー を 作 成 し て い ま す
状態情報を読み取っています...  完了
以 下 の 特 別 パ ッケ ー ジ が イ ン ス ト ー ル されます :
  dbus libdbus-1-3 libexpat1
提案パッケージ:
  dbus-x11
以下のパッケージは「削除」 されます:
  sysvinit
以下のパッケージが新たにインストールされます:
  dbus libdbus-1-3 libexpat1 upstart
警告:  以下の不可欠パッケージが削除されます。
何 を し よ う と し て い る か 本 当 に わ か って い な い 場 合は、 実行してはいけません !
  sysvinit
アップグレード: 0  個、 新規インストール: 4  個、 削除: 1  個、 保留: 9  個。
1,005kB  のアーカイブを取得する必要があります。
こ の 操 作 後 に 追 加 で  2,105kB  のディスク容量が消費されます。
重 大 な 問 題 を 引 き 起 こ す 可 能 性 の あ る こ と を し よ う と し て い ま す 。
続行するには、 ’Yes, do as I say!’  というフレーズをタイプしてください。
 ?] Yes, do as I say!

lxc の環境で試してみましたが、 getty がうまく動かず、 起動しては突然死して、 再起動されて、 ま た突然死、 というのを繰り返してしまうので、 コンソールからのログインは出来ない状態です。 *16

$ sudo lxc-start -n bootsid
cat: /proc/cmdline: No such file or directory
Setting the system clock.
Cannot access the Hardware Clock via any known method.
Use the --debug option to see the details of our search for an access method.
Unable to set System Clock to: Tue Feb 9 14:16:26 UTC 2010 ... (warning).
Activating swap...done.
mount: you must specify the filesystem type
Cannot check root file system because it is not mounted read-only. ... failed!
Setting the system clock.
Cannot access the Hardware Clock via any known method.
Use the --debug option to see the details of our search for an access method.
Unable to set System Clock to: Tue Feb 9 14:16:27 UTC 2010 ... (warning).
Cleaning up ifupdown....
Checking file systems...fsck from util-linux-ng 2.16.2
done.
Setting up networking....
Mounting local filesystems...done.
Activating swapfile swap...done.
Cleaning up temporary files....
Configuring network interfaces...done.
Setting kernel variables ...done.
Cleaning up temporary files....
Starting system message bus: dbus.
Starting OpenBSD Secure Shell server: sshd.
init: tty4 main process (239) terminated with status 1
init: tty4 main process ended, respawning
init: tty5 main process (241) terminated with status 1
init: tty5 main process ended, respawning
init: tty2 main process (242) terminated with status 1
init: tty2 main process ended, respawning
init: tty3 main process (244) terminated with status 1
init: tty3 main process ended, respawning
init: tty6 main process (245) terminated with status 1
init: tty6 main process ended, respawning
init: tty1 main process (306) terminated with status 1
init: tty1 main process ended, respawning
init: tty4 main process (307) terminated with status 1
init: tty4 main process ended, respawning
(snip)

ただし、 ssh 経由のターミナルログインは問題なくできました。

$ ssh bootsid
Enter passphrase for key ’/home/user/.ssh/id_rsa’:
Linux bootsid 2.6.32 #1 SMP Mon Dec 7 05:27:50 UTC 2009 x86_64

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Feb  9 14:18:38 2010 from 192.168.189.114
user@bootsid:~$

/etc/inittab の getty のエントリが残っているので不具合が起きているのか?とも思いましたが、 それは原因ではありませ んでした。 コンソールからログイン出来ないことを除けば一応使えるようです。 KVM/QEMU などの環境で検証しなおしてみ た方が良さそうです。

6.3.2 Lenny での場合

Squeeze/Sid でもうまく行っていない状況ですので、 Squeeze が stable としてリリースされるときに、 検討しましょ う*17 。 あ るいは、 Sid にアップグレードすることを検討しても良いでしょう。

6.3.3 まとめ

現時点では、 問題も抱えているようで、 すんなり問題なく使うのは困難ではありますが、 実際に切り替わった際にはオペレー ション上も多少変更があります。 Ubuntu 9.10 で採用されているネイティブモードでは更にオペレーションも変わるようです ので、 今回はじめて upstart を知ったという方は、 今回をきっかけにぜひ早めに使い方や仕組みを予習しておくと良いで しょう。

第 61 回東京エリア Debian 勉強会 2010 年 2 月
____________________________________________________________________________________________