cron
cronは、Unix系オペレーティングシステムのジョブ管理ツールである。cronジョブ(コマンドまたはシェルスクリプト)を予約すると、指定した日時または間隔でジョブを実行する。cronは、主にシステムの管理・維持を自動化する目的で使用されるが、一定の間隔でファイルや電子メールをインターネットからダウンロードするなどの用途にも応用できる。
cronは、反復的なタスクを予約するのに有用である。一度だけ実行するタスクの予約には、atコマンドを使用する。
名称は、「時間」を指すギリシア語の単語「chronos」に由来する。
概要
cronの動作は、crontab(cron table)ファイルで指定する。crontabは、一定のスケジュールで定期的に実行するシェルコマンドを指定する設定ファイルである。crontabファイルには、ジョブの一覧と、その他のcronデーモンへの指示が記録される。ユーザーは自分のcrontabを作成することができ、通常それとは別に、管理者のみが編集できるシステム全体のcrontabファイルが/etc
またはそのサブディレクトリ(例: /etc/cron.d
)に存在する。
各行は、次の形式でジョブを定義する。
# ┌───────────── 分(0〜59) # │ ┌───────────── 時(0〜23) # │ │ ┌───────────── 日(1〜31) # │ │ │ ┌───────────── 月(1〜12) # │ │ │ │ ┌───────────── 曜日(0〜6〈日〜土〉、一部のシステムでは7も日曜日) # │ │ │ │ │ # │ │ │ │ │ # * * * * * [予約するコマンド]
各行は、コマンドを実行するタイミングを指定する5つの欄に続いて、実行するシェルコマンドを記入するという形式を取る。
通常、日時指定欄がすべて現在の日時と一致する場合にジョブが実行されるが、日(3つ目の欄)と曜日(5つ目の欄)の両方が指定されている(*
ではない)場合、どちらかのみ一致する場合にもジョブが実行される。
例えば、以下は、cronのユーザーのデフォルトのシェルがBourne shellの場合に、Apacheのエラーログを毎日深夜から1分経過後に消去するジョブである。
1 0 * * * printf "" > /var/log/apache/error_log
また、以下は、export_dump.shを毎週土曜日23時45分に実行するジョブである。
45 23 * * 6 /home/oracle/scripts/export_dump.sh
一部のシステムでは、*/n
を指定して、n日・時間・分ごとにジョブを実行することができる。また、コンマを使って複数の時間間隔を指定することもできる(例: 1,2,3
)。例えば、以下の行は、1時から3時55分まで5分ごと(1時0分、1時5分、1時10分、…3時55分)にコマンドラインに「hello world」を出力する。
*/5 1,2,3 * * * echo hello world
各ユーザーは、実際に設定ファイルが保存されている場所によらず、crontab -e
を呼び出して自分の設定ファイルを編集できる。
多くのLinuxディストリビューションにインストールされているポール・ヴィクシーのBSD版cron実装は、ジョ���を実行するアカウントのユーザー名を指定する6番目の欄を追加する。これは、システムのcrontabでのみ許可され、各ユーザーが単独で設定するよう割り当てられたその他のファイルでは使用できない。また、WindowsのnnCronデーモンなど、6番目の欄をアカウントのユーザー名ではなく年の指定に使うものもある。
Amazon EventBridgeのcron実装では、0
を基底とせず、日曜日から土曜日まで1
〜7
で曜日を指定し、月の最初の平日や月末などを指定する追加の機能を持つ。
非標準のマクロ
一部のcron実装は、以下の非標準のマクロをサポートしている。
@reboot
を指定すると、デーモン起動時にジョブが1回実行される。cronは通常再起動されることがないため、これは通常マシンの起動時と一致する。Debian版のcronなど、一部の種類のcronはマシンの起動時にのみ実行するよう設計されており、デーモンの再起動時には@reboot
のジョブが再実行されないようになっている。
@reboot
は、特定のユーザーでサーバーやデーモンを起動する必要があり、ユーザーがプログラムを起動するようinitを設定する権限がない場合に有用である。
cronのパーミッション
次の2つのファイルは重要な役割を担っている。
- /etc/cron.allow – このファイルが存在する場合、cronジョブを使用するにはユーザー名がこのファイルに含まれている必要がある。
- /etc/cron.deny – cron.arrowファイルが存在せず、cron.denyファイルが存在する場合、cronジョブを使用するにはユーザー名がcron.denyファイルに含まれていない必要がある。
どちらのファイルも存在しない場合、サイト固有の設定パラメーターにより、スーパーユーザーのみがcronジョブを使用できるか、すべてのユーザーがcronジョブを使用できるかが決定される。
タイムゾーンの処理
多くのcron実装は、crontabの項目をcronデーモンが実行されているシステムのタイムゾーンの設定に基づいて解釈する。複数のユーザー向けの大規模なマシンで、ユーザーが地理的に複数のタイムゾーンに分散しているケースで、特にシステムのデフォルトのタイムゾーンが混乱を招くおそれのある夏時間を採用している場合、これは問題となる場合がある。このため、cron実装の中には、ユーザーのcrontabのCRON_TZ=[タイムゾーン]
の形式を取る行を認識して、その行以降のcrontabの項目を指定されたタイムゾーンに基づいて解釈するものもある。
式
cronの式は、時間を指定するホワイトスペースで区切られた5つまたは6つの欄の文字列で、特定の作業を予約する。
コメントは#
で始まる。
月と曜日の省略記法は大文字・小文字が区別されない。
システムのcrontabファイル(/etc/crontab)には、コマンドを指定する欄の直前にユーザー名を指定する欄が存在する。この欄は通常root
に設定される。
また、一部の実装では、行の最初に秒の指定欄が存在する場合もある。この場合、各行に6つまたは7つの欄が存在することになる。
- アスタリスク(
*
) - アスタリスク(ワイルドカード)は「すべて」を表す。例えば、
* * * * *
を指定すると、ジョブが毎分実行される。* * * * 1
を指定すると、ジョブが月曜日にのみ毎分実行される。秒の指定に対応している場合、アスタリスクを6個指定するとジョブが毎秒実行される。
- コンマ(
,
) - コンマは、値を複数指定するのに使う。例えば、5番目の欄で
MON,WED,FRI
は「月曜日・水曜日・金曜日」を指す。
- ハイフン(
-
) - ハイフンは範囲を表す。例えば、
2000-2010
は、2000年から2010年までのすべての年を指す。
- パーセント(
%
) - コマンド内のパーセント(
%
)は、バックスラッシュ(\
)でエスケープされていない場合、改行文字に変換され、最初の%
以降のデータが標準入力としてコマンドに渡される。
非標準文字
以下は、Javaのジョブ管理ツールQuartzなど、一部のcron実装にのみ存在する非標準の文字である。
L
L
は「最後の(last)」を意味する。曜日欄で、「最後の金曜日」(5L
)などを指定するのに使う。日欄では、月の最終日を指定するのに使う。
W
W
は、日欄で使用でき、その日に最も近い平日(月曜日〜金曜日)を指定できる。例えば、15W
と記入すると、15日に最も近い平日が指定され、15日が土曜日であれば、14日(金曜日)にジョブが実行される。また、15日が日曜日であれば、16日(月曜日)に実行される。15日が火曜日であれば、そのまま15日(火曜日)に実行される。ただし、日欄に1W
を指定し、1日が土曜日であった場合、ジョブは月を跨がず3日(月曜日)に実行される。W
は、日の範囲指定や一覧指定には使用できない。
- ハッシュ(
#
) #
は、曜日欄で使用でき、この記号に続いて1〜5の数字を指定する。月の「第2金曜日」などを指定するのに使う。例えば、5#3
と記入すると、毎月第3金曜日にジョブが実行される。
- クエスチョンマーク(
?
) - 一部の実装では、月・曜日欄を空欄にする際に
*
の代わりに?
を使う。その他の実装では、?
がデーモンが起動した時間に置き換えられる。例えば、デーモンが午前8時25分に起動した場合には? ? * * * *
が25 8 * * * *
と解釈され、再起動されるまで毎日この時間に実行される。
- スラッシュ(
/
) - Vixie Cronでは、スラッシュは範囲と組み合わせて刻み値を指定するのに使う。例えば、分欄に
*/5
と記入すると、毎5分が指定される。より冗長なPOSIXの5,10,15,20,25,30,35,40,45,50,55,00
の省略表記である。POSIXにはスラッシュの用法に関する定義がない。
H
H
はJenkins継続的インテグレーションシステムで使用できる。例えば、20 * * * *
(毎時20分)を指定する代わりに、H * * * *
を指定して、ジョブを1時間に1回、未指定(ただし一定)の時間に継続的に実行するよう指定できる。これにより、各ジョブがそれぞれ別のタイミングで分散して実行されるようになり、複数のジョブが同じタイミングで実行されてリソースを奪い合うことを防ぐことができる。