2013年4月11日
by kazoo
0 comments
AppStore のデイリー DL 数の取得スクリプトを CentOS の crond で走らせていたのですが、これを Mac 環境に移すことになり、crontab じゃなくてちゃんと launchd でやってみることにしました。
「(Tiger以降の)Mac では crond じゃなく launchd で」というのは聞いた事はあったのですが、そもそもこれが何なのかよくわかっていなかった。launchd が UNIX の init にあたる pid=1 のプロセスなのですね。各種プロセス・デーモンはこいつの子プロセスとして実行される。crontab の定期実行は launchd から起動されるし、イベントの監視や、inetd/xinetd の代わりにネットワークの監視もこいつが行ってくれる。
なるほど。
で、この launchd の設定ファイルが launchd.plist と呼ばれる各種 XML ファイルであり、
以下のようにファイルシステムドメインごとのディレクトリにそれぞれ存在する。1ファイルごとに1サービスの設定となる。
- /System/Library/LaunchAgents/
- /System/Library/LaunchDaemons/
- /Library/LaunchAgents/
- /Library/LaunchDaemons/
- ~/Library/LaunchAgents/
LaunchDaemons ディレクトリにあるのはいわゆるデーモンであり、root権限で走る。(なのでユーザディレクトリには存在しない)。デーモンはログイン状態に関わらず動作する。
LaunchAgents ディレクトリにあるのはエージェントと呼ばれ、ログインしているユーザごとに起動されるプロセスである。全員共通で起動するものを /Library の方に、特定ユーザのみで動作するものを ~/Library の方に書けばよい。
/System/Library/Launch* は基本的に触らない(ハズ)。
launchd.plist はプロパティリストというルールで記述されたXML。
たとえば Adobe のアップデータはこんな感じ。
~/Library/LaunchAgents/com.adobe.AAM.Updater-1.0.plist
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
<?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>Label</key> <string>com.adobe.AAM.Scheduler-1.0</string> <key>Program</key> <string>/Library/Application Support/Adobe/OOBE/PDApp/UWA/UpdaterStartupUtility</string> <key>ProgramArguments</key> <array> <string>/Library/Application Support/Adobe/OOBE/PDApp/UWA/UpdaterStartupUtility</string> <string>-mode=scheduled</string> </array> <key>StartCalendarInterval</key> <dict> <key>Minute</key> <integer>0</integer> <key>Hour</key> <integer>2</integer> </dict> </dict> </plist> |
主要なキー一覧はこちらの表の通り。
dict タグは key タグで囲まれた要素をキーとし、その直後のタグ要素を値とする連想配列を表す。
Label と ProgramArguments のみ必須キーとなっている。
ProgramArguments は最初の配列要素が実行するプログラムのパス、以降が引数となる。
たとえば特定の ruby プログラムを 出力ディレクトリを引数に
$ ruby ~/workspace/test.rb ~/tmp/outdir
というような呼び出しをしたいとすると、
|
.... <key>ProgramArguments</key> <array> <string>ruby</string> <string>/Users/kazoo/workspace/test.rb</string> <string>/Users/kazoo/tmp/outdir</string> </array> |
みたいな感じ。
また、StartCalendarInterval キーは、それに続く連想配列のキー Minute, Hour, Day, WeekDay(0が日曜日), Month の組み合わせで繰り返しが指定できる。Adobe の例ではこのエージェントは毎日 02:00 に実行されることになる。
crond の場合、マシンがスリープしていると実行はスキップされるが、launchd はその復帰時に実行される(複数回の実行が溜まったときは1回だけ実行される)。
また、カレンダー指定でなく単純に時間おきにインターバル実行させたいときは、
|
<key>StartInterval</key> <integer>60</integer> |
のように書くと、60秒毎に実行されるエージェント or デーモンとなる。
標準出力ログを取りたい場合は、StandardOutPath キーでファイルパスを指定してやればよい。
これを指定しなければ、/var/log/system.log にログが書かれるらしいので、それを回避したければ、
|
<key>StandardOutPath</key> <string>/dev/null</string> <key>StandardErrorPath</key> <string>/dev/null</string> |
と、してやる。
最後に、設定ファイルが記述できたら launchctrl コマンドを使ってシステムにロードしてあげましょう。
|
$ launchctrl load ~/Library/LaunchAgents/com.xxxx.kazoo.agent.plist |
このとき、OnDemand キーが true になっていると、ロード時にまず1度実行(デーモンなら最初に1度、エージェントならログインのたびに)される。
また、設定を変更したときは、一度 launchctrl unload してから再度 load する必要があるので注意!
参考:
http://www.itmedia.co.jp/enterprise/articles/0704/26/news009.html
http://www.itmedia.co.jp/enterprise/articles/0704/29/news004.html