argius note

プログラミング関連

Playのアプリ起動をMacOSXのlaunchdで制御する

最近は落雷のせいで電源が瞬断し、UPSのような高級なものは使っておりませんので、常時起動のMac miniが落ちてしまうことが何度か発生しています。
そして、再起動後、Playのアプリが起動してくれません。launchdでアプリを制御しているので、再起動すれば問題ないはずなのです。


原因は単純で、RUNNING_PIDが残ってしまっているからです。
では、どのように解決すれば良いのでしょうか。


アプリの実行環境

RUNNING_PIDを作らないようにする

デフォルトでは、アプリを実行するカレントディレクトリにRUNNING_PIDが作られます。これがpidファイルです。
システムプロパティ"pidfile.path"に任意のパスを設定すると、そのパスのファイルがRUNNING_PIDの代わりにpidファイルになります。
さらに、このプロパティを処理するコード(NettyServer.scala:L.211)を見てみると...どうやら、このプロパティに"/dev/null"を設定すると、pidファイルを無視してくれそうです。

  • 起動(distしたアプリのstartスクリプト)
$ ./start -Dpidfile.path=/dev/null
...(正しく起動されたらしいメッセージが出力される)
$ ll RUNNING_PID
ls: RUNNING_PID: No such file or directory
$
  • 参考:startスクリプトの最終行
exec java $* -cp $classpath play.core.server.NettyServer `dirname $0`


当然ですが、多重起動した場合はportエラーが出るようになります。


launchdで起動したらlaunchdで落とす

playのstopコマンドは、RUNNING_PIDに書いてあるpidのプロセスをkillしてRUNNING_PIDを消す、という動作です。
launchdではpidを管理していますので、わざわざpidを保存する必要は無く、停止させるときはlaunchdで停止(launchctl stop

  • おまけ:start用のplistファイル(app1)
<?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>Disabled</key>
<false/>
<key>KeepAlive</key>
<false/>
<key>Label</key>
<string>local.app1</string>
<key>ProgramArguments</key>
<array>
<string>/var/playapp/app1/start</string>
<string>-Dpidfile.path=/dev/null</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>UserName</key>
<string>root</string>
</dict>
</plist>