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 については、そのうちもっと詳しくまとめたいと思います。