UNIX/Linuxの部屋 crontabコマンドの使い方


※空白区切りで AND 検索 (例:「ファイル 削除」)

コマンド crontab スケジュールを登録。決められた日時・時刻にプログラムを実行する。クーロン。

最終更新


UNIX/Linux の crontab コマンドは定期的に実行するコマンドを登録・確認・管理するコマンドである。

UNIX・Linux では cron または crond というデーモンが常時起動しており、指定の時刻になると指定のコマンドを実行してくれる。crontab コマンドを使うと、その設定ファイルを表示・設定・更新・削除することができる。


crontab 設定方法
日時を指定して、自動的にコマンドを実行することができる。設定方法は
% crontab -e
とすると、エディタが起動して設定内容を更新することができる。エディタは環境変数 EDITOR で自由に設定することができる。しかしながら、e をタイプするつもりが隣の r を押してしまうと、crontab -r で設定内容がクリアされてしまう。当ページ管理人は「crontab -e を使うな」と声を大にして言いたい。

おすすめは、~/.crontab や crontab.txt などのファイルを作り、その中に設定内容を記述した上で、
% crontab 設定ファイル名
→ FreeBSD・Linux の場合
% crontab < 設定ファイル名
→ Solaris の場合
とする方法である。当ページ管理人は、~/.crontab というファイルを作り、このファイルをエディタで編集してから、
% crontab ~/.crontab
として cron に反映する方法を好む。ただし、この方法だと cron に登録されているデータと ~/.crontab の内容が一致している保証はない、という欠点がある。

設定ファイル書式
設定ファイルの書式は
分 時 日 月 曜日 コマンド
である。それぞれの書式は下記のとおり。
分 0-59
時 0-23
日 1-31
月 1-12
曜日 0-7 (0:日曜、1:月曜、2:火曜、3:水曜、4:木曜、5:金曜、6:土曜。7 は 0 と同じ日曜)
それぞれの値は、カンマで結合することで複数指定することができる。例えば「時」のカラムを "6,12,18" とすると、6時・12時・18時を指定できる。また、"2-10" などで範囲指定ができる。さらに FreeBSD・Linux などの一部の crontab では「6-18/2」「*/3」などと、
スラッシュを使うことで「N日おき」「N時間おき」「N分おき」といった指定ができる。
いくつかの例を下記に示す。
* * * * * command
⇒ 1分おき (毎分) に command を実行する。
10 3 1 * * command
⇒ 毎月1日の3時10分に command を実行する。
0 12 * * 0 command
⇒ 毎週日曜日の12時に command を実行する。
0 0,4,8,12,16,20 * * * command
⇒ 0時0分・4時0分・8時0分・12時0分・16時0分・20時0分 に command を実行する。
0 */4 * * * command
⇒ 上記と同じことは "*/4" と書いてもよい ("*/4" は 4時間おきの意味)
10 6-20 * * * command
⇒ 6時〜20時の間、毎時10分に command を実行する (6時10分〜20時10分)。
10 6-20/2 * * * command
⇒ 6時〜20時の間、2時間おきに、毎時10分に command を実行する (6時10分・8時10分〜18時10分・20時10分)。

実行結果はメールで自分自身に知らされる。メールを送ってほしくない場合は、
* * * * * command 1> /dev/null
と標準出力を捨てればよい。この場合はエラーが起こった時だけ (標準エラー出力に出力があった時だけ)メールが送られてくるので便利である。エラーが起ころうと絶対にメールを送ってほしくない場合は
* * * * * command >/dev/null 2>&1
とすればよい。

なお、crontab で実行されるときには、ほとんどの環境変数が設定されていないので注意が必要。~/.cshrc・~/.login で設定している環境変数は設定されていないし、PATH も /bin:/usr/bin くらいにしか通っていない。そのため、command の部分に指定するのはシェルスクリプトにしておいて、シェルスクリプトの先頭で環境変数の設定を行い、その後いろいろなコマンドを実行するようにしておくのがよいだろう。

crontab コマンドのオプション一覧
  • -l 現在設定されている crontab データを表示する
  • -r 現在設定されている crontab データを削除する。
  • -r 現在設定されている crontab データを編集する (エディタが起動する)。
  • -u [ユーザ名] 一般ユーザで crontab コマンドを実行する場合、自分自身の crontab データのみ表示・修正することができる。root で他ユーザの crontab データを更新したい場合、-u オプションでユーザを指定する。
# crontab -u yamada -e
→ ユーザ yamada の crontab データを修正する。
# crontab -u yamada -r
→ ユーザ yamada の crontab データを削除する。

cron を設定した後は、必ず crontab -l で確認すること。もし動作がおかしいなら crontab -r で設定をクリアできるが、その後も必ず crontab -l で確認しよう。

複数コマンド
cron の設定ファイルでは、
* * * * * cd foo/bar; command
というふうに、セミコロンで区切ることで複数のコマンドを記述することができる。その他にもシェルが解釈できる構文や * ? などのメタキャラクタも使用可能である。これは cron は書かれた行をそのままシェルに渡すからである。標準のシェルは sh なので、sh が解釈できるものは何でも書けるというわけだ。

前処理のプログラムが正常終了した場合のみ、次のプログラムを実行したい場合は、
* * * * * command1 && command2
とする。
前処理プログラム A と B を並列実行し、A・B 両方が終了したらプログラム C を実行するには
* * * * * (commandA & commandB & wait) && commandC
とする。

ただし、設定ファイルの先頭で
SHELL=/bin/csh
などと書くと、sh でなく csh に渡されることになり、
* * * * * command >& /dev/null
といった csh 風の書き方ができるようになる (FOO=bar という変数の設定は、少なくとも FreeBSD では可能。他の OS ではダメかもしれない)。

秒単位での指定
cron では、1分より細かい単位で実行することはできない。もし 30秒ごとにコマンドを実行したい場合は
* * * * * command
* * * * * sleep 30 ; command
などと書けばよい。

@reboot で OS 起動時の処理
一部 cron 実装 (vixie-cron の系統を採用している FreeBSD・Linux 等) では、@reboot という書き方によって、OS 起動時に任意の処理を行うことができる。
@reboot command1
ただし、OS 起動だけではなく crond (デーモン) が起動した際、例えば
# service crond restart
などとした際に @reboot が発動するかは実装によるので確認してほしい。

メール送信時のエンコーディング変換
メールは ISO-2022-JP (いわゆる JIS コード) で送るというきまりがあるので、出力が EUC-JP や Shift_JIS などの日本語を含む場合は、
* * * * * command | nkf -j
と、nkf などで ISO-2022-JP に変換すればよい。

注意点: 日と曜日指定は OR である
極めてわかりづらいのだが、日と曜日の組み合わせだけは「OR」である。
0 0 1 * 2 command1
は、毎月1日の 0時0分と、毎週火曜日の 0時0分に実行される。よって、crontab の通常書式だけでは「13日の金曜日」を表現することはできない。当ページ管理人のネット上の観測によると、これにハマる人はとても多いようなので要注意である。

注意点: 年の指定
crontab で年の指定はできない。「今年のある処理は2017年3月18日に起動するが、来年は未定。そもそも来年実行するかどうかも未定」となったとしても、
0 0 18 3 * command
と年なしで書かなくてはならない。来年忘れそうで不安である。そういときは
0 18 3 * [ `date +\%Y` -eq 2017 ] && command
としてはどうか。上記コードは未テストなので注意。
注意点: 誤って毎分起動
毎日12時に起動しようとして、
0 12 * * * command
と書くつもりが、
* 12 * * * command
と書いてしまい、12時00分〜12時59分の毎分起動になってしまうミスはありがちである。しかも排他処理をサボっていたりすると、プロセス終了前に次のプロセスが起動してしまい、数十個のプロセスが実行中になり、負荷が高くなってしまうのもありがちである。

注意点: % のエスケープ
上記で
0 18 3 * [ `date +\%Y` -eq 2017 ] && command
と書いたが、crontab データ上では % は改行を表すので、"date +%Y" は "date +\%Y" とエスケープする必要がある。

余談: Azure の crontab 定義
マイクロソフト Azure の WebJob で crontab 定義ができるのだが、そこでは
秒 分 時 日 月 曜日 コマンド
と先頭に「秒」が追加されている。

cron の欠点
cron の欠点は以下の通り。
  • 1分単位でしか起動できない。例えば n 秒おきに起動、ということができない (できなくはないが、Tips3 のように小細工が必要になる)。
  • 登録した時刻にマシンが起動していないと、永遠に起動されない。
  • 指定した日が祝日なら、次の営業日に実行、というちょっと凝った指定ができない。
  • 重複起動防止の機能はない。プログラムを毎分実行するように設定したとして、もしプログラムの実行に 1分以上かかってしまっても、新たにプロセスがどんどん生成される。重複起動を避けたい場合は、個々のプログラムで排他制御をする必要がある。
  • Tips.4 のように、cron にて前処理・後処理を行うことは可能だが、「前処理のプログラムが異常終了した場合に手動リカバリ後にその次のプログラムから再開」といった賢いリカバリ作業はできない。

cron は中小規模のシステムでは全く問題ないものの、大規模な商用システムでは上記のような欠点があるために、JP1・Senju(千手)・Hinemos・Tivoli などのジョブ管理ツールを使うことが多い。例えば、
0時からバッチA→バッチB→バッチC を実行し、3時からバッチD→バッチE を実行し、バッチC とバッチE の完了を待ってバッチFを実行するときにバッチBが異常終了した際、夜間監視を行なっているオペレータがバッチB以降を再実行する
といった運用があったとして、cron なりコマンドラインなりで完結させるのはなかなかに難しい。上記のジョブ管理ツールは GUI 画面を提供し、どの箇所でエラーになったのか・エラー内容は何かをわかりやすく表示し、ボタンひとつで再実行できたりする。
>> FreeBSDオンラインマニュアル(man) FreeBSD crontab(1)
>> Linuxオンラインマニュアル(man) Linux crontab(1)
>> Linuxオンラインマニュアル(man) Linux crontab(5)
>> Solaris10オンラインマニュアル(man) Solaris10 crontab(1)


頑張って書いたおすすめコンテンツ!
クラウドサービス徹底比較・徹底解説