Edited at

launchdで定期的にスクリプトを実行

More than 1 year has passed since last update.

定期的にスクリプトを実行する場合、Mac OS Xではcrontabよりlaunchdを使うことが推奨されている。

launchdを用いてMac OS Xで定期的にスクリプトを実行する方法を記述。


特徴


  • 設定が2種類ある:



    • エージェントはユーザーがログイン中に実行できるプログラム。


    • デーモンはシステム共通で、誰もログインしていなくても実行できるプログラム。



  • 前回の実行が終わらないと次の実行は始まらない。また、スリープ状態、シャットダウン状態では実行されない。1

  • 標準でCPU時間メモリファイル等の使用の制限2が設けられている。必要に応じて設定ファイルで上限を上げないと、シグナルで届いてしまう。

設定ファイルを置く場所は次の通り。

場所
用途

~/Library/LaunchAgents/<Label>.plist
ユーザーごと設定できるエージェント

/Library/LaunchAgents/<Label>.plist
管理者用のエージェント

/Library/LaunchDaemons/<Label>.plist
システム共通のデーモンrootがオーナー)

Label はユニークな識別名。ファイルはplist形式3


単純なサンプル

一定間隔で実行と、特定の時間に実行する方法がある。


10秒間隔でスクリプトを実行

次を満たすサンプルを作る。


  • 実行するのは一般ユーザー所有のスクリプト:test.rb

  • 10秒ごとに実行するエージェントとして設定する。

  • STDOUT/STDERR出力をファイルに保存(test.out/test.err)。

識別名(Label)はtestにするので設定ファイルはtest.plist

一般ユーザー所有のエージェントスクリプトなので~/Library/LaunchAgents/に置く。


設定ファイル:~/Library/LaunchAgents/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>/usr/bin/ruby</string>
<string>-Ku</string>
<string>/Users/mofu/script/test.rb</string>
</array>
<key>StartInterval</key>
<integer>10</integer>
<key>StandardOutPath</key>
<string>/Users/mofu/script/test.out</string>
<key>StandardErrorPath</key>
<string>/Users/mofu/script/test.err</string>
</dict>
</plist>

次のコマンドで登録すると、実行されるようになる。

$ launchctl load ~/Library/LaunchAgents/test.plist

これ以降、システムを再起動してもこのユーザーでログインすれば設定が維持され、実行が再開する。

登録解除するには次のコマンドを使う。

$ launchctl unload ~/Library/LaunchAgents/test.plist

これ以降、実行されなくなる。


毎日、0時0分にスクリプトを実行

次を満たすサンプルを作る。


  • 実行するのは一般ユーザー所有のスクリプト:test2.rb

  • 毎日、0時間0分に実行するエージェントとして設定する。

  • STDOUT/STDERR出力をファイルに保存(test2.out/test2.err)。

識別名はtest2とするので設定ファイルはtest2.plist

一般ユーザー所有のエージェントスクリプトなので~/Library/LaunchAgents/に置く。


設定ファイル:~/Library/LaunchAgents/test2.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>test2</string>
<key>ProgramArguments</key>
<array>
<string>/usr/bin/ruby</string>
<string>-Ku</string>
<string>/Users/mofu/script/test2.rb</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>0</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>StandardOutPath</key>
<string>/Users/mofu/script/test2.out</string>
<key>StandardErrorPath</key>
<string>/Users/mofu/script/test2.err</string>
</dict>
</plist>

次のコマンドで登録。

$ launchctl load ~/Library/LaunchAgents/test2.plist


用途ごとサンプル


iOSアプリのデイリービルドデーモン

次を満たすサンプルを作る。


  • スクリプトbuild.shをシステム共通で(ログインしていない状態でも)実行できるようにする。

  • すなわちデーモンとして設定する。実行するタイミングは毎日0時間0分。

  • デーモンとして設定するのでroot所有の設定だが、スクリプトの実行ユーザーはmofuとする。

  • 各種制限に引っかからないよう、上限を設定する。


    • 処理時間:1,200秒(標準は20秒である)。

    • CPU時間:1,200秒。

    • 最大メモリ:2,000,000,000バイト。

    • 最大ファイルサイズ:2,000,000,000バイト。



  • 環境変数を設定:CocoaPodsのpod installのためLC_ALLen_US.UTF-8に。

  • ワーキングディレクトリを/Users/mofu/scriptに設定。

  • STDOUT出力をファイルに保存(build.out)。

識別名はbuildとするので設定ファイルはbuild.plist

システム共通のデーモンスクリプトなので/Library/LaunchDaemons/に置き、rootを所有者にする。


設定ファイル:/Library/LaunchDaemons/build.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>build</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/mofu/script/build.sh</string>
</array>
<key>StartCalendarInterval</key>
<dict>
<key>Hour</key>
<integer>0</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<key>StandardOutPath</key>
<string>/Users/mofu/script/build.out</string>
<key>WorkingDirectory</key>
<string>/Users/mofu/script</string>
<key>EnvironmentVariables</key>
<dict>
<key>LC_ALL</key>
<string>en_US.UTF-8</string>
</dict>
<key>UserName</key>
<string>mofu</string>
<key>SessionCreate</key>
<true />
<key>ExitTimeOut</key>
<integer>1200</integer>
<key>SoftResourceLimits</key>
<dict>
<key>CPU</key>
<integer>1200</integer>
<key>FileSize</key>
<integer>2000000000</integer>
<key>Data</key>
<integer>2000000000</integer>
</dict>
<key>HardResourceLimits</key>
<dict>
<key>CPU</key>
<integer>1200</integer>
<key>FileSize</key>
<integer>2000000000</integer>
<key>Data</key>
<integer>2000000000</integer>
</dict>
</dict>
</plist>

次のコマンドで設定ファイルのオーナーをrootにし、登録する。

$ sudo chown root /Library/LaunchDaemons/build.plist

$ sudo launchctl load /Library/LaunchDaemons/build.plist

※iOSビルドスクリプトについてはこちらに記述。


平日のみ、毎日10時にスクリプトを実行

次を満たすサンプルを作る。


  • スクリプトweekdays.shをデーモンとして実行する。

  • 実行するタイミングは平日のみ、毎日10時。


設定ファイル:/Library/LaunchDaemons/weekdays.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>weekdays</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>/Users/mofu/script/weekdays.sh</string>
</array>
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Weekday</key>
<integer>1</integer>
<key>Hour</key>
<integer>10</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Weekday</key>
<integer>2</integer>
<key>Hour</key>
<integer>10</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Weekday</key>
<integer>3</integer>
<key>Hour</key>
<integer>10</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Weekday</key>
<integer>4</integer>
<key>Hour</key>
<integer>10</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Weekday</key>
<integer>5</integer>
<key>Hour</key>
<integer>10</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</array>
</dict>
</plist>

次のコマンドで設定ファイルのオーナーをrootにし、登録する。

$ sudo chown root /Library/LaunchDaemons/weekdays.plist

$ sudo launchctl load /Library/LaunchDaemons/weekdays.plist


設定項目の一覧

定期的にスクリプトを実行するために使う設定。


識別名【必須】

ジョブを識別するためのユニークな文字列で構成された識別名Labelに指定する。

ファイル名にもこの文字列を使う。


Label

<key>Label</key>

<string>mofu.build.daily</string>


何を実行するか【必須】

ProgramArgumentsに、実行するプログラムパラメータを指定する。


ProgramArguments

<key>ProgramArguments</key>

<array>
<string>/bin/bash</string>
<string>/Users/mofu/script/build.sh</string>
</array>


いつ実行するか

一定間隔ならStartInterval秒数を指定する。


StartInterval

<key>StartInterval</key>

<integer>10</integer>

特定の時間に実行するならStartCalendarIntervalに時間を指定する。



  • Minute


  • Hour時間


  • Day


  • Weekday曜日(0と7は日曜日)


  • Month


StartCalendarInterval

<key>StartCalendarInterval</key>

<dict>
<key>Hour</key>
<integer>0</integer>
<key>Minute</key>
<integer>0</integer>
</dict>

複数の時間を指定することもできる。


StartCalendarInterval、配列

<key>StartCalendarInterval</key>

<array>
<dict>
<key>Hour</key>
<integer>10</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>19</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</array>


どの環境で実行するか

WorkingDirectoryワーキングディレクトリを指定できる。


WorkingDirectory

<key>WorkingDirectory</key>

<string>/Users/mofu/script</string>

EnvironmentVariablesに、環境変数を指定できる。


EnvironmentVariables

<key>EnvironmentVariables</key>

<dict>
<key>LC_ALL</key>
<string>en_US.UTF-8</string>
</dict>

UserNameに、スクリプトを実行するユーザーを指定できる。


UserName

<key>UserName</key>

<string>mofu</string>

そのユーザーのセッションを作成した上で実行したい場合はSessionCreateを指定できる。(デーモンでもログインキーチェインが使える状態になる。)


SessionCreate

<key>UserName</key>

<string>mofu</string>
<key>SessionCreate</key>
<true />


処理時間の制限

ExitTimeOutに処理の制限時間秒数で設定できる。標準は20秒。

この時間が経過するとプロセスにSIGKILLシグナルが送られる。


ExitTimeOut

<key>ExitTimeOut</key>

<integer>1200</integer>


リソースの制限

SoftResourceLimitsHardResourceLimitsに、ソフト制限、ハード制限を設定できる。

ソフト制限を超えるとプロセスにシグナルが送られるがハート制限未満までなら実行を続けられる。

主な設定項目4



  • CPU:各プロセスに使用される最大CPU時間(秒)。


  • Data:使用できる最大メモリ(バイト)。


  • FileSize:作成できるファイルの最大サイズ(バイト)。


SoftResourceLimits、HardResourceLimits

<key>SoftResourceLimits</key>

<dict>
<key>CPU</key>
<integer>1200</integer>
<key>FileSize</key>
<integer>2000000000</integer>
<key>Data</key>
<integer>2000000000</integer>
</dict>
<key>HardResourceLimits</key>
<dict>
<key>CPU</key>
<integer>1200</integer>
<key>FileSize</key>
<integer>2000000000</integer>
<key>Data</key>
<integer>2000000000</integer>
</dict>


参照





  1. スリープの場合、スリープ中に実行するタイミングが来ていた場合、スリープから復帰したときに直ちに実行される。 



  2. 処理時間、CPU使用時間、メモリ、スタック、同時に開くファイル数、ファイルサイズ等。 



  3. Property List、XML形式。テキストエディタで編集可能。 



  4. 必要に応じて設定できる他のキー:CoreMemoryLockNumberOfFilesNumberOfProcessesResidentSetSizeStack。