Hatena::ブログ(Diary)

kanonjiの日記 RSSフィード

http://kanonji.info/blog/ 2013年2月頃に移転しました。

2010-06-21

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 の代わりにネットワークのポートを監視して、プロセスの起動を行う。
  • ファイルやフォルダを監視し、ファイルの追加や更新をトリガーにして、プロセスの起動を行う。

環境

MacMac OS X 10.5.8(Leopard)

デーモンをサービスとして登録する

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説明必須
Labellaunchd のジョブの名前。ユニークな名前を付ける。必須か慣例か分からないけど、ファイル名もこのLabelに.plistという拡張子を付けたものにする。 必須
ProgramArguments実行するプログラムとオプションや引数を、例の通りarrayノードに入れ子で書く。必須
KeepAlivetrueなら常に起動するようにlaunchdががんばる。起動したプロセスをkillしてもすぐ立ち上げなおされる。bool型以外にdictionary型で細かい指定が可能らしい。falseがデフォルト値
RunAtLoadtrue なら 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 のキー一覧

the inner universe of Leopard - 「rcの引退とlaunchdの強化」 (6) 表1: Leopardで追加された、launchdの新しい設定項目(キーワード)一覧 | マイナビニュース

the inner universe of Leopard - 「rcの引退とlaunchdの強化」 (7) 表2: Tigerまでに利用できるlaunchdの設定項目(キーワード)一覧 | マイナビニュース

launchd.plistを書くGUIツール

no title

launchd.plist はXMLで、更にkeyノードの次にそのノードに対応した値ノードが来るという、ちょっと変わった文法なので、あまり手で書きたくはありません。

オープンソースで Lingon.app というツールがあるので、これを使います。

ただ、更新が2008年で止まってるので、Lingonで作った launchd.plist を一部修正して使います。

具体的には、指定して無いのに WatchPaths というキーと QueueDirectories というキーが指定されているってだけなんですけど。

値ノードが空なので、たぶん問題は無いと思うけど一応その2つは vi で消しました。

f:id:kanonji:20100621073027p:image

上から順に、(1)で Label を書いて、(2)で ProgramArguments を書いて、(3)で KeepAlive と RunAtLoad を含むいくつかのキーが設定できるだけって感じです。

f:id:kanonji:20100621073028p:image

新しい設定を作る時、最初にタイプを選ぶダイアログがでます。

この説明は次で。

Daemon と Agent

Daemon
システムの一部としてバックグラウンドで動作するプロセス。特定のユーザーと結びついていない。GUIが持てない。
Agent
特定のユーザー用のバックグラウンドプロセス。GUIが持てる。

ざっくりと言えばこんな感じです。


~/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 はジョブラベルを指定します。

より詳しい使い方はGuides and Sample Code

非推奨な手段

起動項目(SystemStarter)

/Library/StartupItemsディレクトリ入れるもので、Windowsで言うところのスタートアップの様なものだったと思います。

StartupItems も LaunchDaemons 知らなかったので、最初はこれを混同しちゃってましたが、launchd とは別の仕組みみたいです。

OS X 10.4からは起動項目に代わり、launchd の使用が推奨されています。

inetdおよびxinetdデーモン

OS X 10.4 からは launchd の使用が推奨されてます。

cron

cronについてはドキュメントが見つかりませんでした。

参考

  1. the inner universe of Leopard - 「rcの引退とlaunchdの強化」 (1) goodby "rc" | マイナビニュース
  2. LaunchDaemons (launchctl, launchd.plist) の使い方 - maruko2 Note.
  3. Page Not Found - Apple Developer
  4. Undocumented Mac OS X:第1回 initを置き換えるlaunchd【前編】 (1/3) - ITmedia エンタープライズ
  5. コマンド/launchctl - MacWiki

*1:KeepAlive true な設定をしたプロセスは stop しても直ぐ立ち上げ直されます。止めるには unload です。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証