Mac OSにおける、initや/etc/rcやcronの代わりであるlaunchdの使い方
Mac OSはUNIXベースですが、デーモンの起動や管理にはRunCommandを使わなくなっています。
OS X 10.4(Tiger)から、UNIXのPID 1のプロセスはinitでしたが、それに代わって launchd が導入されました。
OS X 10.5(Leopard)では、一応残っていた /etc/rc が無くなりました。
起動時にデーモンを立ち上げたり、デーモンのコントロールに /etc/rc が使えないので、launchd の仕組みを調べてみました。
概要
間違いがあるかもというか、誤解を招くかもしれないけど、ざっくりと。
- launchd は init の代わりにPID 1で最初に起動して、初期化やシェルの起動を行う。
- /etc/rc は無くなったけど一部残ってる /etc/rc.common などのrcスクリプトを実行する。
- /etc/rc のrcスクリプトの代わりに launchd.plist を使う。
- cron の代わりに時刻をトリガーにしたプロセスの起動をする。
- inetd/xinetd の代わりにネットワークのポートを監視して、プロセスの起動を行う。
- ファイルやフォルダを監視し、ファイルの追加や更新をトリガーにして、プロセスの起動を行う。
デーモンをサービスとして登録する
rcスクリプトの代わりにXMLで記述する launchd.plist を作ります。
$ ls -al /Library/LaunchDaemons/ total 40 drwxr-xr-x 7 root wheel 238 6 21 07:07 . drwxrwxr-t+ 57 root admin 1938 12 8 2009 .. -rw-r--r-- 1 root wheel 694 5 29 2009 de.jinx.SmartSleepDaemon.plist -rw-r--r-- 1 root wheel 412 6 21 03:13 kanonji.gnump3d.plist lrwxr-xr-x 1 root wheel 66 10 22 2009 org.freedesktop.dbus-system.plist -> /opt/local/Library/LaunchDaemons/org.freedesktop.dbus-system.plist -rw-r--r-- 1 root wheel 474 5 26 2008 org.pqrs.KeyRemap4MacBook.load.plist -rw-r--r-- 1 root wheel 470 5 25 2008 org.pqrs.PCKeyboardHack.load.plist
置き場所はここです。
/Library/LaunchDaemons/ は root:wheel 所有なので、ここにファイルを作る時は sudo します。
$ less kanonji.gnump3d.plist <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>KeepAlive</key> <true/> <key>Label</key> <string>kanonji.gnump3d</string> <key>ProgramArguments</key> <array> <string>/usr/bin/gnump3d</string> <string>--fast</string> </array> <key>RunAtLoad</key> <true/> </dict> </plist>
最近インストールした GNUMP3d 用の launchd.plist を作ったので、例にしてみます。
key | 説明 | 必須 |
Label | launchd のジョブの名前。ユニークな名前を付ける。必須か慣例か分からないけど、ファイル名もこのLabelに.plistという拡張子を付けたものにする。 | 必須 |
ProgramArguments | 実行するプログラムとオプションや引数を、例の通りarrayノードに入れ子で書く。 | 必須 |
KeepAlive | trueなら常に起動するようにlaunchdががんばる。起動したプロセスをkillしてもすぐ立ち上げなおされる。bool型以外にdictionary型で細かい指定が可能らしい。 | falseがデフォルト値 |
RunAtLoad | true なら launchd に launchd.plist がロードされたタイミングで起動する。 | 不明 |
この設定で、OSを起動したら /usr/bin/gnump3d --fast が呼ばれて起動します。
KeepAlive true なら、プロセスが落ちても立ち上げなおしてくれるみたいです。
$ launchctl load /Library/LaunchDaemons/kanonji.gnump3d.plist
launchd.plist を書いたら、launchd のCUIツールである launchctl でロードします。
RunAtLoad があるので、ロードしたら gnump3d が起動しました。
ちなみに、RunAtLoad true は一応書いたけど、もしかすると KeepAlive true なら不要かもしれない。
KeepAlive true だけで launchd.plist をロードしても、gnump3d は起動してました。
OS起動時はどうなるかはまだ未確認です。
launchd.plistを書くGUIツール
launchd.plist はXMLで、更にkeyノードの次にそのノードに対応した値ノードが来るという、ちょっと変わった文法なので、あまり手で書きたくはありません。
オープンソースで Lingon.app というツールがあるので、これを使います。
ただ、更新が2008年で止まってるので、Lingonで作った launchd.plist を一部修正して使います。
具体的には、指定して無いのに WatchPaths というキーと QueueDirectories というキーが指定されているってだけなんですけど。
値ノードが空なので、たぶん問題は無いと思うけど一応その2つは vi で消しました。
上から順に、(1)で Label を書いて、(2)で ProgramArguments を書いて、(3)で KeepAlive と RunAtLoad を含むいくつかのキーが設定できるだけって感じです。
新しい設定を作る時、最初にタイプを選ぶダイアログがでます。
この説明は次で。
Daemon と Agent
ざっくりと言えばこんな感じです。
~/Library/LaunchAgents/ | My Agents | ホームディレクトリ内なので、自分用のエージェント |
/Library/LaunchAgents/ | Users Agents | ユーザで共有のエージェント |
/Library/LaunchDaemons/ | Users Daemons | デーモン |
Lingon のダイアログで、3つのタイプがありましたが launchd.plist の置き場所によって変わります。
gnump3d は名前の最後に d がある様に、デーモンなので /Library/LaunchDaemons/ に設置しました。
/System/Library/LaunchAgents/ と /System/Library/LaunchDaemons/
Lingon の左側にも SYSTEM AGENTS と SYSTEM DAEMONS とあります。
これはたぶん、OS X のシステムの設定と思われるので、ユーザーが追加したり変更したりというのは、基本的に必要ないと思います。
ここにあるという事を覚えておけば、トラブル時に解決の糸口を探れるかもしれません。
launchctlの使い方
$ launchctl list PID Status Label 3440 - 0x112230.launchctl 3388 - [0x0-0x166166].org.lingon.Lingon 2597 - 0x112950.bash 2596 - 0x112860.login 2533 - 0x111390.bash 2532 - 0x111ae0.login 592 - [0x0-0x42042].org.mozilla.thunderbird 574 - [0x0-0x3f03f].com.apple.AppleSpell 中略 - 1 kanonji.gnump3d 以下略
ロード済みの設定を一覧に表示します。
PID に数字が書いてあればプロセスが起動してます。
Status の意味はちょっと調べきれてません。
$ launchctl load /Library/LaunchDaemons/kanonji.gnump3d.plist $ vi /Library/LaunchDaemons/kanonji.gnump3d.plist $ launchctl unload /Library/LaunchDaemons/kanonji.gnump3d.plist $ launchctl load /Library/LaunchDaemons/kanonji.gnump3d.plist
ロードとアンロードは launchd.plist を指定します。
launchd.plist を変更した場合、一旦 unload して再度 load が必要です。
$ launchctl start kanonji.gnump3d $ launchctl stop kanonji.gnump3d
start や stop*1 はジョブラベルを指定します。
より詳しい使い方はDocumentation Archive。
非推奨な手段
起動項目(SystemStarter)
/Library/StartupItemsディレクトリ入れるもので、Windowsで言うところのスタートアップの様なものだったと思います。
StartupItems も LaunchDaemons 知らなかったので、最初はこれを混同しちゃってましたが、launchd とは別の仕組みみたいです。
OS X 10.4からは起動項目に代わり、launchd の使用が推奨されています。
inetdおよびxinetdデーモン
OS X 10.4 からは launchd の使用が推奨されてます。
cron
cronについてはドキュメントが見つかりませんでした。
参考
*1:KeepAlive true な設定をしたプロセスは stop しても直ぐ立ち上げ直されます。止めるには unload です。