launchdの時刻指定を複数時刻にしたい

launchdの作業ディレクトリ(Lingon 3を使ってplist作成) - 別館 子子子子子子(ねこのここねこ)
の続きです。
cronだと次のような"*"(ワイルドカード)記法が使えます。

# 毎2時間おきに date コマンドを実行

0 0,2,4,6,8,10,12,14,16,18,20,22 * * * date >> /var/log/date.log

wikipedia:Crontab

一方、Mac OS Xにはcronの代わりにlaunchdのplistで時刻指定をします。

     StartCalendarInterval 
     This optional key causes the job to be started every calendar interval as specified. Missing arguments
     are considered to be wildcard. The semantics are much like crontab(5).  Unlike cron which skips job
     invocations when the computer is asleep, launchd will start the job the next time the computer wakes
     up.  If multiple intervals transpire before the computer is woken, those events will be coalesced into
     one event upon wake from sleep.

           Minute 
           The minute on which this job will be run.

           Hour 
           The hour on which this job will be run.

           Day 
           The day on which this job will be run.

           Weekday 
           The weekday on which this job will be run (0 and 7 are Sunday).

           Month 
           The month on which this job will be run.

launchd.plist(5) Mac OS X Manual Page

ということで、

echo test

というシェルスクリプトを0, 15, 30, 45分に実行するtest.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>Label</key>
	<string>test</string>
	<key>ProgramArguments</key>
	<array>
		<string>echo</string>
		<string>test</string>
	</array>
	<key>StartCalendarInterval</key>
	<array>
		<dict>
			<key>Minute</key>
			<integer>0</integer>
		</dict>
		<dict>
			<key>Minute</key>
			<integer>15</integer>
		</dict>
		<dict>
			<key>Minute</key>
			<integer>30</integer>
		</dict>
		<dict>
			<key>Minute</key>
			<integer>45</integer>
		</dict>
	</array>
</dict>
</plist>

crontabと違う点は三つ。

今回は分(Minute)キーだけを指定して、時(Hour)日(Day)曜日(Weekday)および月(Month)は省略しているので、毎時の指定になります。

  • 値は整数限定で" * / 2 "などの表記は不可

全ての時刻を書く必要があります。まぁ1分毎とかの場合は秒指定であるStartIntervalキーを使って"60"とかしておけば良いと思いますけど。

  • StartCalendarIntervalキーの取る値がdictのarrayになる

Lingonで作られたStartCalendarIntervalキーはdictのみなので、書き換えて複数時刻にする場合にはarrayタグの組が必要になります。

Lingon 3 App

カテゴリ: ユーティリティ

価格: ¥250

特に最後の点に注意してplistを書いてください。

時分指定

dictの中に時分組み合わせを入れます。
例えば0時, 4時, 13時, 20時それぞれの正時を指定する場合。

	<key>StartCalendarInterval</key>
	<array>
		<dict>
			<key>Hour</key>
			<integer>0</integer>
			<key>Minute</key>
			<integer>0</integer>
		</dict>
		<dict>
			<key>Hour</key>
			<integer>4</integer>
			<key>Minute</key>
			<integer>0</integer>
		</dict>
		<dict>
			<key>Hour</key>
			<integer>13</integer>
			<key>Minute</key>
			<integer>0</integer>
		</dict>
		<dict>
			<key>Hour</key>
			<integer>20</integer>
			<key>Minute</key>
			<integer>0</integer>
		</dict>
	</array>

時と分を各々dictの中に一つだけ入れておくと、指定した分と、指定した時の各分で起動してしまいます。

おまけ

曜日(Weekday)に関しては一つのキーで複数指定可能だそうです(確認してません)。
なお0または7が日曜日なので、日月火水木金土日=01234567のように対応します。

try this too. Working for me!

	<key>StartCalendarInterval</key>
	<dict>
		<key>Minute</key>
		<integer>00</integer>
		<key>Hour</key>
		<integer>22</integer>
		<key>Weekday</key>
		<integer>12345</integer>
	</dict>

osx - What's the difference between 'Day' and 'Weekday' in launchd StartCalendarInterval? - Stack Overflow