plist ファイルの代わりに YAML を使ってみた


OS X で launchd に登録する時には plist というフォーマット (バイナリもしくは XML) の設定ファイルを使う必要がある。
ところがこれが XML かつ、ちょっと癖があって dict とか key とか string とか、なかなか XML らしくもない。
なれるまでとても読みにくい。読めても書きたくない。

↓ は、サンプルとして、 1 分おきに terminal-notifier をつかって「はろー」と通知する設定。

$ terminal-notifier -message 'はろー'

<?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>sample-launchd</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/terminal-notifier</string>
        <string>-message</string>
        <string>はろー</string>
    </array>
    <key>StandardOutPath</key>
    <string>/tmp/sample-output.txt</string>
    <key>StartInterval</key>
    <integer>60</integer>
</dict>
</plist>

こんなのを記憶して空で書ける気がしない。crontab なら 1 行くらいで書けるし、たぶん手が覚えている。
launchd にフラストレーションが貯まっていく。

そこで対策を考えてみた。

人間にとって読みやすい、 YAML で書くのだ。

YAML

StandardOutPath: /tmp/sample-output.txt
StartInterval: 60
ProgramArguments:
  - /usr/local/bin/terminal-notifier
  - -message
  - はろー
Label: sample-launchd

これなら読める。かなり読める。ちょっと覚えれば手で書けるレベル。

そして OS X には plutil というツールが含まれていて、これは JSON を上記の plist 用の XML 形式に変換できる。

$ yaml2json < some_daemon.yaml | plutil -convert xml1 - -o some_daemon.plist

としてやれば、普通の plist になる。あとはいつもどおり。

$ launchctl load some_daemon.plist

と読ませてやることができる。もちろん止めるときは unload 。

他にも思いつく応用例

自分では試してないけど plist をマージしなきゃいけないつらさがある iOS の開発とかで使えるんじゃないだろうか。

補足

yaml2json

実験で使った yaml2json なるコマンドは https://www.npmjs.com/package/yaml2json で入れることができる。

おそらく自分の誤りで ↑ の通りでは意図していた挙動になっていなかった。 ↓ のエイリアスが意図した挙動だった。

あるいは、 Python 環境があるなら PyYAML をインストールした上で、

$ python -c 'import sys, yaml, json; json.dump(yaml.load(sys.stdin), sys.stdout, indent=4)'

のようなコマンドを yaml2json にエイリアスすればいい。

terminal-notifier

$ brew install terminal-notifier

でインストールできる。わりと便利。

launchd のスケジューリング

この記事では「 YAML でできるよね」という内容だけを扱った。
細かいスケジューリングの方法まで知りたい方は Apple のドキュメント読もう

Scheduling Timed Jobs

訂正: cron について

この記事を最初に書いた時に OS X 上の cron について考え違いをしていた。ごめんなさい。
↓ のように書いていましたが、普通に使える。

OS X で定期実行させるには launchd 用に設定を読み書きしなくてはならない。
色々と設定すれば crontab も使えるようになるらしいが、デフォルトでは cron は止まってる。

参考: http://qiita.com/kegamin/items/e035304e7295750cdf7d