rcの一番の問題点は、シェルスクリプトであるということだ。もちろん、シェルスクリプトであることは、先に述べたようにrcの可読性を高める利点であり、UNIXらしい実装の例ともいえる。しかし、特にrcのスクリプトではどうしても逐次的に処理を記述してしまう形になってしまい、並列性に劣るところがある。初期のMac OS Xの起動が遅かったのは、マシンパワーよりもこうした起動スクリプトの逐次性で「処理を待たされる」ことが多かったのも一因だ。

テキストファイルであるがため、シェルスクリプトを記述できる熟練者にとって見れば構成に柔軟性があるが、そうではない初心者や、プログラムを使って構成を直すのは難しい。IPアドレスから設置場所から何から何まで固定され、熟練のシステム管理者が存在することが前提だった過去のUNIXと、周囲の環境に合わせ絶えず変更されうる、ノートパソコンとして持ち歩かれ場所すら一定しないのも当然で、使い手がごく一般的なユーザである現代のMac OS Xでは、必ずしも同じことが利点となるとは限らない。

そして一番の問題としては、rcに記述されている処理が必ずしも起動時に必要とは限らず、一方で起動時以外にもそうした処理を柔軟に実行、停止したい場合もあることだ。例えばネットワーク関連の初期化処理は、起動時だけではなく、アップルメニューから「ネットワーク環境」を切り替えたときにも必要となる。時刻で処理やサービスを実行してほしいときもあれば、ネットワークを介したリクエストに応じて起動してほしいときもある。

もちろんrcベースでも、LinuxのSysV initのように部分ごとの起動停止(/sbin/service httpd stopなど)をサポートしたものもあり、cronを使えば時刻による実行が行え、inetd / xinetdによりネットワークからのリクエストに対処できる。しかし、rc、cron、inetd / xinetd ではそれぞれそのための登録方法がばらばらで、統合されていない。ユーザはもちろん、開発者としてもそうしたサービスを利用するのは敷居が高くなっていた。

こうした問題に対処したのが、Tigerのlaunchdだ。launchdはlaunchd.plistという一連の書式で、起動時や時刻、あるいはTCP/IPやMach IPCによるリクエストに応じての処理の実行がサポートされる。launchdはSystemStarterやSysV initなどによる解決よりも優れた、非常にエレガントな機構だ。

Tigerでこのlaunchdが登場し、rcよりも優れた起動手段が提供された時点で、rcの退場は予定されていたようなものだったのだ。

run commandの引越し先

これまで、rcに記載されていた処理はすべてlaunchdにより実行される。最低限の処理はlaunchdの内部で行われ、そしてそれ以外の、従来rcに書かれていた処理やSystemStarterで実行されていた処理はすべてLaunchDaemonに移された。

例えば、ページング処理のサポートを行うdynamic_pagerはこれまで/etc/rcで起動されるよう記述されていたが(リスト4)、これは/System/Library/LaunchDaemons/com.apple.dynamic_pager.plistに記述されており、launchdからOS起動時に実行される(リスト5)。同様に、これまでSystemStarterから起動されていた処理も、launchdで起動されるようになった。

リスト4: Tigerの/etc/rcの一節(dynamic_pagerの起動部分を抜粋)。このように、スクリプトでべた書きされている

   …
   …
   if [ ${ENCRYPTSWAP:=-NO-} = "-YES-" ]; then
       encryptswap="-E"
   else
       encryptswap=""
   fi
   /sbin/dynamic_pager ${encryptswap} -F ${swapdir}/swapfile
   …
   …

リスト5: Leopard上の「/System/Library/LaunchDaemons/com.apple.dynamic_pager.plist」。Leopardでは、launch.plistに書き換えられlaunchdにより他のサービスと並列的に起動されるようになった


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
                     <key>Label</key>
                     <string>com.apple.dynamic_pager</string>
                     <key>ProgramArguments</key>
                     <array>
                            <string>/sbin/dynamic_pager</string>
                            <string>-F</string>
                            <string>/private/var/vm/swapfile</string>
                     </array>
                     <key>OnDemand</key>
                     <false/>
</dict>
</plist>

互換性

デフォルトでrcは存在しないが、互換性のためrc関連の機能はいまだ残されている。例えば、rcやStartupItemsから読み込まれることの多い/etc/rc.commonはまだ残されており、起動処理に必要な定数やサポート関数などが存在している。また、/etc/rc.localを作成した場合、従来と同じように実行される。

Mac OS X自身は使わなくなったSystemStarterだが、StartupItemsの仕組み自体はいまだサポートされている。

リスト6にあるように、/Library/StartupItemsないしは/System/Library/StartupItemsは、何らかのファイルかフォルダがあった場合に限り、launchdを介して/sbin/SystemStarterが起動される。

リスト6: 何らかのファイルかフォルダがあった場合に限り、launchdを介して/sbin/SystemStarterが起動される


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.apple.SystemStarter</string>
    <key>Program</key>
    <string>/sbin/SystemStarter</string>
    <key>KeepAlive</key>
    <dict>
        <key>PathState</key>
        <dict>
            <key>/etc/rc.local</key>
            <true/>
            <key>/etc/rc.shutdown.local</key>
            <true/>
        </dict>
    </dict>
    <key>QueueDirectories</key>
    <array>
        <string>/Library/StartupItems</string>
        <string>/System/Library/StartupItems</string>
    </array>
    <key>HopefullyExitsFirst</key>
    <true/>
</dict>
</plist>

なお、/Library/StartupItemsはデフォルトでは存在しないか存在しても空のフォルダであり、Leopardでは/System/Library/StartupItemsも空のフォルダとなっている。アップグレードインストールを行う、あるいは移行アシスタントを使ってTiger以前の環境を移行することで、/Library/StartupItemsに何らかのStartupItemが残ってしまったときだけに使われるだけだ。