launchdでmongoDBを自動起動

以下のようなplistを書いて ~/Library/LaunchAgent/local.mongodb.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>
    <false/>
    <key>RunAtLoad</key>
    <true/>
    <key>Label</key>
    <string>local.mongodb</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/mongod</string>
        <string>--port=27017</string>
        <string>--rest</string>
        <string>--dbpath=/Users/hoge/apps/mongodb/data</string>
    </array>
    <key>StandardErrorPath</key>
    <string>/dev/null</string>
    <key>StandardOutPath</key>
    <string>/dev/null</string>
</dict>
</plist>

dbpathは好きな場所でよいが、自分のユーザ権限で起動するので、自分のホームディレクトリ以下の適当な場所を選ぶと良いだろう。

で、plistをlaunchdにサブミットする。

$ launchctl load  ~/Library/LaunchAgent/local.mongodb.plist

mongoDBが起動すればOK。今後このユーザでログインした時にも自動起動する。

停止/起動の方法は

$ launchctl stop local.mongodb
$ launchctl start local.mongodb

forkオプション

mongoDBのforkオプションは必ずoffで起動すること。

mongoDBにはデーモンとして起動するためのforkオプションがあるが、launchdを使うときはonにしてはいけない。forkしてしまうとmongoDBのプロセスがlaunchdの制御から離れてしまうため、launchctl stopコマンドで停止できなくなる*1

またforkオプションとlaunchdのKeepAliveオプションを併用してはいけない。KeepAliveをtrueにしてしまうと、mongoDBがforkして親プロセスが死ぬとlaunchdはmongoDBの再起動を試みる。ポートが既に使われているため起動には失敗するが、launchdはmongoDBを生かし続けようとして永遠に起動処理を(既に起動しているにも関わらず!)繰り返すことになる。

一般的にlaunchdでプロセスを管理する場合は、自前でdaemon化したりforkしてはいけません。

*1:もちろんpidを調べてkillすればOK、ちなみにlaunchctl stopはSIGTERMをプロセスに送る