launchd を使ってスクリプトを自動実行してみた
launchd を使った自動処理
Unix ではデーモンやプロセス、スクリプト等の自動実行には init や crond などを用いて行うのが一般的です。
しかし、Mac OS X はこれらの機能をまとめた laucnd というサービス管理フレームワークを使って、システムの起動時や指定時間にデーモンやプロセス、スクリプト等の自動実行を行っています。利点として、ブート時間の短縮や一元管理などがあるそうです。
私は Mac OS X Server を運用しているのですが、時々、カレンダーサーバが動作しなくなってしまうことがあり、いちいちカレンダーサーバ機能を再起動しなければなりませんでした。原因について調べても情報がみつからず、手動で再起動させるのも面倒くさいので、自動でカレンダーサーバ機能のみを再起動させたいと思います。
Mac は一応 crond を使えるので、そっちで処理するのもありですが、launchd を触る機会にもなるので、今回は、毎日午前3時にカレンダーサーバを再起動するスクリプトを launchd.plist で作成し、launchd で自動実行させたいと思います。
ターミナル上でのカレンダーサーバの停止と起動コマンド
まず、OS X Server のカレンダーサーバ機能を停止、起動するコマンドは以下のようになります。
[bash]
#カレンダーサーバ機能を停止
sudo serveradmin stop calendar
#カレンダーサーバ機能を起動
sudo serveradmin start calendar
[/bash]
このコマンドを launchd.plist で作成して、毎日3時に自動実行させることになります。
launchd.plist ファイルの作成
カレンダーサーバの停止、起動にはいくらか時間がかかるので、停止処理と起動処理を別々の plist ファイルを作成し、停止処理の 5 分後に起動処理をさせることにします。
下記のように各処理のファイルを作成します。なお、ファイルは一から作成するのではなく、どこからか *.plist ファイルを持ってきて、それをコピーするようにしたほうがいいらしいです。
カレンダーサーバ停止処理
stop.calendar_server.plist
[xml]
<?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>hicc.stop.calendar_server</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Server.app/Contents/ServerRoot/usr/sbin/serveradmin</string>
<string>stop</string>
<string>calendar</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Minute</key>
<integer>0</integer>
<key>Hour</key>
<integer>3</integer>
</dict>
</dict>
</plist>
[/xml]
カレンダーサーバ起動処理
start.calendar_server.plist
[xml]
<?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>start.calendar_server</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Server.app/Contents/ServerRoot/usr/sbin/serveradmin</string>
<string>start</string>
<string>calendar</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Minute</key>
<integer>5</integer>
<key>Hour</key>
<integer>3</integer>
</dict>
</dict>
</plist>
[/xml]
上記 plist ファイルにおいて、
[xml]
<key>ProgramArguments</key>
<array>
<string>/Applications/Server.app/Contents/ServerRoot/usr/sbin/serveradmin</string>
<string>start</string>
<string>calendar</string>
</array>
[/xml]
が、実行したいコマンド部分、
[xml]
<key>StartCalendarInterval</key>
<dict>
<key>Minute</key>
<integer>5</integer>
<key>Hour</key>
<integer>3</integer>
</dict>
[/xml]
が、毎日3時に実行する日時指定部分になります。
launchd.plist ファイルの launchd 関連のディレクトリへの格納
launchd.plist は launchd が管理する以下のディレクトリに格納しなければなりません。
- ~/Library/LaunchAgents
各ユーザが管理する各ユーザユーザごとに実行するエージェントの格納ディレクトリ
- /Library/LaunchAgents
管理者が管理するする各ユーザごとに行するのエージェントの格納ディレクトリ
- /Library/LaunchDaemons
管理者が管理するシステムで実行するデーモンの格納ディレクトリ(ログイン状態に依らない)
- /System/Library/LaunchAgents
OS が管理する各ユーザごとに実行するエージェントの格納ディレクトリ(基本的には触らない)
- /System/Library/LaunchDaemons
OS が管理するシステムで実行するデーモンの格納ディレクトリ(基本的には触らない)
今回は、OS X Server に関することで、スーパーユーザ権限が必要なため、 /Library/LaunchDaemons にファイルを格納します。また、同時に実行権限も付加します。
[bash]
#ファイルを launchd ディレクトリに格納
sudo cp ./stop.calendar_server.plist /Library/LaunchDaemons/
sudo cp ./start.calendar_server.plist /Library/LaunchDaemons/
#実行権限を付加
chmod 755 /Library/LaunchDaemons/stop.calendar_server.plist
chmod 755 /Library/LaunchDaemons/start.calendar_server.plist
[/bash]
Launchd への登録
最後に作成したファイルを launchd へ登録します。登録には launchctl コマンドを用います。
下記コマンドを実行。
[bash]
#launchd へ plist ファイルを登録
sudo launchctl load /Library/LaunchDaemons/stop.calendar_server.plist
sudo launchctl load /Library/LaunchDaemons/start.calendar_server.plist
[/bash]
ここでエラーが発生する場合は、plist ファイルの構文がおかしい可能性がありますので、ソースコードをチェックしましょう。
以上で、launchd への自動実行処理の登録は終了です。ログを確認して、正常に動作しているか確認しましょう。
ログは plist ファイルに指定していない場合、/var/log/system.log に出力されます。
ログファイルを別に出力したい場合は、plist ファイルに下記のような内容を追加します。
[xml]
<key>StandardOutPath</key>
<string>/var/calendar.log</string>
<key>StandardErrorPath</key>
<string>/var/calendar_error.log</string>
[/xml]
launchd へ登録した後に plist ファイルを修正する場合
launchd へ登録した後に plist ファイルを修正する場合は、下記のように一度 unload してから、もう一度 load し直す必要があります。
[bash]
#修正後
sudo launchctl unload /Library/LaunchDaemons/start.calendar_server.plist
sudo launchctl load /Library/LaunchDaemons/start.calendar_server.plist
[/bash]
launchd については、そのうちもっと詳しくまとめたいと思います。